team-3/src/c3nav/site/models.py

94 lines
3.1 KiB
Python
Raw Normal View History

from contextlib import contextmanager
2017-12-10 15:23:53 +01:00
from django.conf import settings
2017-12-10 15:40:28 +01:00
from django.core.cache import cache
from django.db import models, transaction
2017-12-08 00:35:17 +01:00
from django.db.models import Q
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from c3nav.mapdata.fields import I18nField
class Announcement(models.Model):
created = models.DateTimeField(auto_now_add=True, verbose_name=_('created'))
active_until = models.DateTimeField(null=True, verbose_name=_('active until'))
active = models.BooleanField(default=True, verbose_name=_('active'))
2017-12-10 15:23:53 +01:00
author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT, verbose_name=_('author'))
text = I18nField(_('Text'), fallback_any=True)
2017-12-08 00:35:17 +01:00
class Meta:
verbose_name = _('Announcement')
verbose_name_plural = _('Announcements')
default_related_name = 'announcements'
get_latest_by = 'created'
@classmethod
def get_current(cls):
result = cache.get('site:announcement', False)
if result is not False:
2017-12-10 15:40:28 +01:00
return result
2017-12-08 00:35:17 +01:00
try:
2017-12-10 15:40:28 +01:00
result = cls.objects.filter(Q(active=True) & (Q(active_until__isnull=True) |
Q(active_until__gt=timezone.now()))).latest()
2017-12-08 00:35:17 +01:00
except cls.DoesNotExist:
2017-12-10 15:40:28 +01:00
result = None
timeout = 300
if result and result.active_until:
2017-12-10 15:40:28 +01:00
timeout = max(0, min(timeout, (result.active_until-timezone.now()).total_seconds()))
cache.set('site:announcement', result, timeout)
return result
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
cache.delete('site:announcement')
2017-12-24 01:13:44 +01:00
class SiteUpdate(models.Model):
"""
A site update that asks the user to reload the page.
"""
created = models.DateTimeField(auto_now_add=True, verbose_name=_('create'))
class Meta:
verbose_name = _('Site update')
verbose_name_plural = _('Site updates')
default_related_name = 'siteupdates'
get_latest_by = 'created'
@classmethod
@contextmanager
def lock(cls):
with transaction.atomic():
try:
yield cls.objects.select_for_update().get(pk=cls.objects.earliest().pk)
except cls.DoesNotExist:
yield
@classmethod
def last_update(cls):
last_update = cache.get('site:last_site_update', None)
if last_update is not None:
return last_update
with cls.lock():
try:
last_update = cls.objects.latest()
except cls.DoesNotExist:
last_update = None
else:
last_update = last_update.pk
cache.set('site:last_site_update', last_update, None)
return last_update
def save(self, **kwargs):
new = self.pk is None
with transaction.atomic():
super().save(**kwargs)
if new:
transaction.on_commit(
lambda: cache.set('site:last_site_update', self.pk, None)
)