Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
mpicms/mpicms/events/models.py
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
144 lines (118 sloc)
4.67 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
from datetime import datetime, date, timedelta | |
from ics import Calendar, Event as ICSEvent | |
from django.db import models | |
from django.core.exceptions import ValidationError | |
from django.utils.translation import gettext_lazy as _ | |
from wagtail.admin.edit_handlers import FieldPanel, MultiFieldPanel | |
from wagtail.images.edit_handlers import ImageChooserPanel | |
from wagtail.core.models import Page | |
from wagtail.api import APIField | |
from mpicms.base.mixins import BasePage, BodyMixin | |
class Event(BodyMixin, BasePage): | |
start_date = models.DateField(_('start date')) | |
end_date = models.DateField(_('end date'), blank=True, null=True) | |
start_time = models.TimeField(_('start time'), blank=True, null=True) | |
end_time = models.TimeField(_('end time'), blank=True, null=True) | |
room = models.CharField(_('Room'), max_length=10, blank=True) | |
external = models.BooleanField(default=False) | |
header_image = models.ForeignKey( | |
'wagtailimages.Image', | |
null=True, | |
blank=True, | |
on_delete=models.SET_NULL, | |
related_name='+' | |
) | |
show_in_menus_default = False | |
parent_page_types = ['events.EventIndex'] | |
subpage_types = [] | |
content_panels = Page.content_panels + BodyMixin.content_panels + [ | |
ImageChooserPanel('header_image'), | |
MultiFieldPanel( | |
[ | |
FieldPanel('external'), | |
FieldPanel('start_date'), | |
FieldPanel('start_time'), | |
FieldPanel('end_date'), | |
FieldPanel('end_time'), | |
], | |
heading=_('event dates') | |
), | |
FieldPanel('room') | |
] | |
promote_panels = Page.promote_panels + BodyMixin.promote_panels | |
api_fields = BodyMixin.api_fields + [ | |
APIField('start_date'), | |
APIField('end_date'), | |
APIField('start_time'), | |
APIField('end_time'), | |
APIField('room') | |
] | |
@property | |
def start(self): | |
if self.start_time: | |
return datetime.combine(self.start_date, self.start_time).astimezone() | |
return self.start_date | |
@property | |
def end(self): | |
if self.end_time: | |
date = self.end_date or self.start_date | |
return datetime.combine(date, self.end_time).astimezone() | |
return self.end_date | |
def get_dict(self, request=None): | |
datetime_end = self.end | |
if self.end_date and not self.end_time: | |
datetime_end += timedelta(days = 1) | |
return { | |
'title': self.title, | |
'start': self.start.isoformat(), | |
'end': datetime_end.isoformat() if self.end else None, | |
'url': self.get_url(request=request), | |
} | |
def clean(self): | |
"""Clean the model fields, if end_date is before start_date raise a ValidationError.""" | |
super().clean() | |
if self.end_date and self.end_date < self.start_date: | |
raise ValidationError({'end_date': 'The end date cannot be before the start date.'}) | |
if self.end_time and not self.start_time: | |
raise ValidationError({'end_time': 'The end time cannot be set without a start time.'}) | |
if self.end and self.end < self.start: | |
raise ValidationError({'end_time': 'The end time cannot be before the start time.'}) | |
class Meta(object): # noqa | |
ordering = ['start_date'] | |
verbose_name = _('event') | |
verbose_name_plural = _('events') | |
class EventIndex(BasePage): | |
parent_page_types = ['base.RootPage'] | |
subpage_types = ['events.Event'] | |
@property | |
def events(self): | |
if self.depth <= 3: | |
return Event.objects.live().specific() | |
return self.get_children().type(Event).live().specific() | |
def get_json_events(self, request=None, external=False): | |
event_dicts = [ event.get_dict(request) for event in self.events.filter(external=external) ] | |
return json.dumps(event_dicts) | |
def clean(self): # Prevent more than one event index | |
model = self.__class__ | |
if (model.objects.count() > 0 and self.pk != model.objects.get().id): | |
raise ValidationError("Can only create 1 %s instance" % model.__name__) | |
@property | |
def ics(self): | |
c = Calendar() | |
for event in self.events.filter(external=False): | |
e = ICSEvent( | |
name=event.title, | |
begin=event.start, | |
end=event.end, | |
description=event.search_description, | |
url=event.full_url, | |
location=event.room | |
) | |
if type(event.start) is date: | |
e.make_all_day() | |
c.events.add(e) | |
return c | |
class Meta: # noqa | |
verbose_name = _('event index') | |
verbose_name_plural = _('event indexes') |