Dynamically find currently active Contest
Previously we had a lot of hardcoded contest information in the templates. Name, ruleset and number of contest are now all taken from the currently active contest and rendered into the templates. Instead of an URL containing the current contest name, we just use a generic /contest/. The API will no longer use "the contest with id=1", but the currently active contest as well. The currently active contest is - for now - the contest with the latest deadline.
This commit is contained in:
parent
7ae53b6150
commit
1f93f9e7bd
|
@ -0,0 +1,7 @@
|
||||||
|
from .models import Contest
|
||||||
|
|
||||||
|
|
||||||
|
def current_contest(self):
|
||||||
|
return {
|
||||||
|
'current_contest': Contest.get_current_contest(),
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated by Django 4.0.1 on 2022-01-22 17:52
|
||||||
|
|
||||||
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('contest', '0021_alter_qso_otherno_alter_qso_ownno_alter_user_dncall_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='contest',
|
||||||
|
name='contestNo',
|
||||||
|
field=models.IntegerField(default=1, help_text='Running number of contest (for vanity reasons)', validators=[django.core.validators.MinValueValidator(1)]),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Generated by Django 4.0.1 on 2022-01-22 17:56
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('contest', '0022_contest_contestno'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='contest',
|
||||||
|
name='rulesetLink',
|
||||||
|
field=models.TextField(default='', help_text='URL to the ruleset pdf for this contest'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
|
@ -12,6 +12,9 @@ from .validators import CallUsernameValidator
|
||||||
class Contest(models.Model):
|
class Contest(models.Model):
|
||||||
name = models.CharField(max_length=20)
|
name = models.CharField(max_length=20)
|
||||||
shortName = models.CharField(max_length=20, unique=True)
|
shortName = models.CharField(max_length=20, unique=True)
|
||||||
|
contestNo = models.IntegerField(validators=[MinValueValidator(1)],
|
||||||
|
help_text="Running number of contest (for vanity reasons)")
|
||||||
|
rulesetLink = models.TextField(help_text="URL to the ruleset pdf for this contest")
|
||||||
callQrg = models.ForeignKey("Frequency", on_delete=models.SET_NULL, null=True, blank=True)
|
callQrg = models.ForeignKey("Frequency", on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
deadline = models.DateTimeField()
|
deadline = models.DateTimeField()
|
||||||
|
|
||||||
|
@ -23,7 +26,12 @@ class Contest(models.Model):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_current_contest(cls):
|
def get_current_contest(cls):
|
||||||
return cls.objects.get(id=1)
|
# Currently the contest with the latest deadline is the active one
|
||||||
|
# This definitely has potential for improvement, but it's better than a hardcoded contest
|
||||||
|
contests = cls.objects.order_by("-deadline")
|
||||||
|
if len(contests) > 0:
|
||||||
|
return contests[0]
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class Reference(models.Model):
|
class Reference(models.Model):
|
||||||
|
|
|
@ -40,6 +40,7 @@ INSTALLED_APPS = [
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
'django.contrib.humanize',
|
||||||
'crispy_forms',
|
'crispy_forms',
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
'django_filters',
|
'django_filters',
|
||||||
|
@ -72,6 +73,7 @@ TEMPLATES = [
|
||||||
'django.template.context_processors.request',
|
'django.template.context_processors.request',
|
||||||
'django.contrib.auth.context_processors.auth',
|
'django.contrib.auth.context_processors.auth',
|
||||||
'django.contrib.messages.context_processors.messages',
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
'contest.context_processors.current_contest',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,7 +7,7 @@ from contest.views import index, register, profile
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', index, name="index"),
|
path('', index, name="index"),
|
||||||
path('cqtufm2019/', include('contest.urls', namespace='contest')),
|
path('contest/', include('contest.urls', namespace='contest')),
|
||||||
|
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
path('login/', auth_views.LoginView.as_view(), name='login'),
|
path('login/', auth_views.LoginView.as_view(), name='login'),
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<link rel="icon" href="/favicon.ico">
|
<link rel="icon" href="/favicon.ico">
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
||||||
<title>CQTUFM2019 - CQ TU FM Contest 2019</title>
|
<title>{{ current_contest.name }}</title>
|
||||||
|
|
||||||
<!-- Bootstrap core CSS -->
|
<!-- Bootstrap core CSS -->
|
||||||
<link href="{% static "css/bootstrap.min.css" %}" rel="stylesheet">
|
<link href="{% static "css/bootstrap.min.css" %}" rel="stylesheet">
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
</button>
|
</button>
|
||||||
<a class="navbar-brand" href="{% url "index" %}">CQ TU FM 2019</a>
|
<a class="navbar-brand" href="{% url "index" %}">{{ current_contest.name | default:"NO CONTEST" }}</a>
|
||||||
</div>
|
</div>
|
||||||
<div id="navbar" class="navbar-collapse collapse">
|
<div id="navbar" class="navbar-collapse collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
|
@ -88,7 +88,7 @@
|
||||||
|
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<p class="text-muted">CQ TU FM 2019, a <a href="http://dk0tu.de/">DK0TU</a> product</p>
|
<p class="text-muted">{{ current_contest.name }}, a <a href="http://dk0tu.de/">DK0TU</a> product</p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<p>
|
<p>
|
||||||
Welcome to {{ contest.name }}!
|
Welcome to {{ contest.name }}!
|
||||||
<p/>
|
<p/>
|
||||||
<p>Here you can find a short overview over the rules, but note that this is not a replacement for the <a href="http://dk0tu.de/contests/cqtu/CQTU_2017-02-02_FM_Rules+Log.300dpi.pdf">complete ruleset</a>.</p>
|
<p>Here you can find a short overview over the rules, but note that this is not a replacement for the <a href="{{ current_contest.rulesetLink }}">complete ruleset</a>.</p>
|
||||||
<p>
|
<p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Change frequency after a successful CQ-call! If you answered, feel free to call CQ on this frequency.</li>
|
<li>Change frequency after a successful CQ-call! If you answered, feel free to call CQ on this frequency.</li>
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
|
{% load humanize %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<p class="lead">Hello and welcome to the 4th DK0TU CQ TU contest, the CQ TU 2019!</p>
|
{% if current_contest %}
|
||||||
|
<p class="lead">Hello and welcome to the {{ current_contest.contestNo | ordinal }} DK0TU CQ TU contest, the {{ current_contest.name }}!</p>
|
||||||
|
{% else %}
|
||||||
|
<p class="lead">ERROR: No contest set in admin area! If you're an admin <a href="/admin/">go create one</a>.</p>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue