time-based competition state + smart cache
authorJan Szejko <janek37@gmail.com>
Thu, 9 Nov 2017 15:49:04 +0000 (16:49 +0100)
committerJan Szejko <janek37@gmail.com>
Thu, 9 Nov 2017 15:49:04 +0000 (16:49 +0100)
edumed/settings/custom.py
edumed/settings/locale.py
requirements.txt
wtem/models.py
wtem/views.py

index fc95db1..3be9e89 100644 (file)
@@ -3,3 +3,6 @@
 CONTACT_FORMS_MODULE = 'edumed.contact_forms'
 
 MAX_UPLOAD_SIZE = 20 * 1024 * 1024
+
+OLIMPIADA_START = (2017, 11, 23, 10)
+OLIMPIADA_END = (2017, 11, 23, 11)
index cfe4cc1..6aa42c7 100644 (file)
@@ -15,7 +15,7 @@ LANGUAGES = (
 # timezone as the operating system.
 # If running in a Windows environment this must be set to the same as your
 # system time zone.
-TIME_ZONE = None
+TIME_ZONE = 'Europe/Warsaw'
 
 # Language code for this installation. All choices can be found here:
 # http://www.i18nguy.com/unicode/language-identifiers.html
index 2a776b2..d1fde75 100644 (file)
@@ -39,4 +39,6 @@ pyyaml
 
 django-subdomains>=2.0.4,<2.1
 
-unidecode
\ No newline at end of file
+unidecode
+
+pytz
\ No newline at end of file
index fbf0928..390687f 100644 (file)
@@ -4,6 +4,10 @@ import string
 import os
 import json
 
+from datetime import datetime
+
+import pytz as pytz
+from django.conf import settings
 from django.core.validators import validate_email
 from django.db import models
 from django.contrib.auth.models import User
@@ -23,6 +27,8 @@ f.close()
 
 DEBUG_KEY = 'smerfetka159'
 
+tz = pytz.timezone(settings.TIME_ZONE)
+
 
 def get_exercise_by_id(exercise_id):
     return [e for e in exercises if str(e['id']) == str(exercise_id)][0]
@@ -34,6 +40,10 @@ def make_key(length):
         for i in range(length))
 
 
+def tuple2dt(time_tuple):
+    return tz.localize(datetime(*time_tuple))
+
+
 class CompetitionState(models.Model):
     """singleton"""
     BEFORE = 'before'
@@ -46,9 +56,19 @@ class CompetitionState(models.Model):
     )
     state = models.CharField(choices=STATE_CHOICES, max_length=16)
 
+    start = tuple2dt(settings.OLIMPIADA_START)
+    end = tuple2dt(settings.OLIMPIADA_END)
+
     @classmethod
     def get_state(cls):
-        return cls.objects.get().state
+        now = timezone.now()
+        if now < cls.start:
+            return cls.BEFORE
+        elif now < cls.end:
+            return cls.DURING
+        else:
+            return cls.AFTER
+        # return cls.objects.get().state
 
 
 class Submission(models.Model):
index d47a2be..a532732 100644 (file)
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 import json
 from copy import deepcopy
+from functools import wraps
 
 from django.conf import settings
 from django.contrib import messages
@@ -8,6 +9,8 @@ from django.core.urlresolvers import reverse
 from django.http import HttpResponseForbidden
 from django.http.response import HttpResponseRedirect
 from django.shortcuts import render, get_object_or_404
+from django.utils import timezone
+from django.utils.cache import patch_cache_control, add_never_cache_headers
 from django.views.decorators.cache import never_cache
 from django.views.decorators.csrf import csrf_exempt
 
@@ -16,6 +19,20 @@ from .forms import WTEMForm, WTEMSingleForm
 from .models import Submission, DEBUG_KEY, exercises, CompetitionState
 
 
+def cache_until_start(view_func):
+    @wraps(view_func)
+    def _wrapped_view_func(request, *args, **kwargs):
+        response = view_func(request, *args, **kwargs)
+        max_age = max(int((CompetitionState.start - timezone.now()).total_seconds()) + 1, 0)
+        if max_age:
+            patch_cache_control(response, max_age=max_age)
+        else:
+            add_never_cache_headers(response)
+        return response
+
+    return _wrapped_view_func
+
+
 @csrf_exempt
 def form(request, submission_id, key):
     state = CompetitionState.get_state()
@@ -24,6 +41,7 @@ def form(request, submission_id, key):
     return globals()['form_' + state](request, submission_id, key)
 
 
+@cache_until_start
 def form_before(request, submission_id, key):
     submission = Submission.objects.get(id=submission_id)
     if submission.key != key:
@@ -108,7 +126,7 @@ def form_single(request, submission_id, key):
             raise Exception
 
 
-@never_cache
+@cache_until_start
 @csrf_exempt
 def start(request, submission_id, key):
     state = CompetitionState.get_state()