-
jan.bednarik authoredjan.bednarik authored
models.py 2.62 KiB
import arrow
import requests
from django.contrib.postgres.fields import JSONField
from django.core.serializers.json import DjangoJSONEncoder
from django.db import models
from .parser import process_ical
def _convert_arrow_to_datetime(event):
event["begin"] = event["begin"].datetime
event["end"] = event["end"].datetime
return event
class EventsJSONField(JSONField):
"""
JSONField for lists of events which converts `begin` and `end` to datetime
on load from DB.
"""
def from_db_value(self, value, expression, connection):
if value:
for event in value:
event["begin"] = arrow.get(event["begin"]).datetime
event["end"] = arrow.get(event["end"]).datetime
return value
class Calendar(models.Model):
ACTUAL_NUM = 6
url = models.URLField()
source = models.TextField(null=True)
last_update = models.DateTimeField(null=True)
past_events = EventsJSONField(encoder=DjangoJSONEncoder, null=True)
future_events = EventsJSONField(encoder=DjangoJSONEncoder, null=True)
def update_source(self):
source = requests.get(self.url).text
if self.source != source:
self.source = source
past, future = process_ical(source)
self.past_events = list(map(_convert_arrow_to_datetime, past))
self.future_events = list(
reversed(list(map(_convert_arrow_to_datetime, future)))
)
self.last_update = arrow.utcnow().datetime
self.save()
def actual_events(self):
return self.future_events[-self.ACTUAL_NUM :]
class CalendarMixin(models.Model):
"""
Mixin to be used in other models, like site settings, which adds relation
to Calendar.
"""
calendar_url = models.URLField(
"URL kalendáře ve formátu iCal", blank=True, null=True
)
calendar = models.ForeignKey(
Calendar, null=True, blank=True, on_delete=models.PROTECT
)
class Meta:
abstract = True
def save(self, *args, **kwargs):
# create or update related Calendar
if self.calendar_url:
if self.calendar:
if self.calendar.url != self.calendar_url:
self.calendar.url = self.calendar_url
self.calendar.save()
else:
self.calendar = Calendar.objects.create(url=self.calendar_url)
self.calendar.update_source()
# delete related Calendar when URL is cleared
if not self.calendar_url and self.calendar:
self.calendar.delete()
self.calendar = None
super().save(*args, **kwargs)