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:
Sebastian Lohff 2022-01-22 19:11:47 +01:00
parent 7ae53b6150
commit 1f93f9e7bd
9 changed files with 68 additions and 7 deletions

View File

@ -0,0 +1,7 @@
from .models import Contest
def current_contest(self):
return {
'current_contest': Contest.get_current_contest(),
}

View File

@ -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,
),
]

View File

@ -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,
),
]

View File

@ -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):

View File

@ -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',
], ],
}, },
}, },

View File

@ -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'),

View File

@ -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>

View File

@ -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>

View File

@ -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>