From d2e2fc529f15b60a8fa6a1da0e45b70003011fb5 Mon Sep 17 00:00:00 2001 From: Jan Szejko Date: Thu, 9 Nov 2017 16:49:04 +0100 Subject: [PATCH] time-based competition state + smart cache --- edumed/settings/custom.py | 3 +++ edumed/settings/locale.py | 2 +- requirements.txt | 4 +++- wtem/models.py | 22 +++++++++++++++++++++- wtem/views.py | 20 +++++++++++++++++++- 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/edumed/settings/custom.py b/edumed/settings/custom.py index fc95db1..3be9e89 100644 --- a/edumed/settings/custom.py +++ b/edumed/settings/custom.py @@ -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) diff --git a/edumed/settings/locale.py b/edumed/settings/locale.py index cfe4cc1..6aa42c7 100644 --- a/edumed/settings/locale.py +++ b/edumed/settings/locale.py @@ -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 diff --git a/requirements.txt b/requirements.txt index 2a776b2..d1fde75 100644 --- a/requirements.txt +++ b/requirements.txt @@ -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 diff --git a/wtem/models.py b/wtem/models.py index fbf0928..390687f 100644 --- a/wtem/models.py +++ b/wtem/models.py @@ -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): diff --git a/wtem/views.py b/wtem/views.py index d47a2be..a532732 100644 --- a/wtem/views.py +++ b/wtem/views.py @@ -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() -- 2.20.1