Files
kasu/src/events/models.py
Xeniac c5781246fe Added a setting where the exported excel files should be stored.
Added a option to send the exported excel as mail attachment.
2017-12-07 09:40:35 +01:00

324 lines
10 KiB
Python

"""Models to solitary events, events series with an location and photos."""
import os
from ckeditor.fields import RichTextField
from django.conf import settings
from django.core.exceptions import ValidationError
from django.urls import reverse
from django.db import models
from django.db.models import Q
from django.template.defaultfilters import slugify
from django.utils.timezone import now
from django.utils.translation import ugettext as _
from easy_thumbnails.fields import ThumbnailerImageField
from utils import COUNTRIES, OverwriteStorage
from .managers import EventManager
def get_upload_path(instance, filename):
"""
Generates the desired file path and filename for an uploaded Image.
With this function Django can save the uploaded images to subfolders that
also have a meaning for humans.
@param instance: an Django Object for which the Image has been uploaded.
@type instance: a instace of an models.Model sub-class.
@param filename: The filename of the uploaded image.
@type filename: String
"""
filename, extension = os.path.splitext(filename.lower())
if isinstance(instance, Event):
return "events/{date:%Y-%m-%d}/{name}{ext}".format(
date=instance.start,
name=slugify(instance.name),
ext=extension
)
elif isinstance(instance, Location):
return "events/locations/{name}{ext}".format(
name=slugify(instance.name),
ext=extension
)
elif isinstance(instance, Photo):
return "events/{date:%Y-%m-%d}/{name}{ext}".format(
date=instance.event.start,
name=filename,
ext=extension
)
class Event(models.Model):
"""An Event that could be a tournament, a game session, or an convention."""
name = models.CharField(_('Name'), max_length=255)
description = RichTextField(_("Description"), blank=True)
location = models.ForeignKey('Location')
start = models.DateTimeField(_('Start'))
end = models.DateTimeField(_('End'), blank=True, null=True)
url = models.URLField(_('Homepage'), blank=True)
image = ThumbnailerImageField(
_("Image"),
upload_to=get_upload_path,
storage=OverwriteStorage(),
blank=True,
null=True
)
mahjong_tournament = models.BooleanField(
_('Mahjong Tournament'),
default=False,
help_text=_(u'This event is a tournament, different rules apply for \
the kyu ranking.')
)
mahjong_season = models.PositiveSmallIntegerField(
_('Mahjong Season'),
blank=True,
null=True
)
photo_count = models.PositiveIntegerField(default=0, editable=False)
event_series = models.ForeignKey(
'Event',
blank=True,
null=True,
on_delete=models.SET_NULL, editable=True,
verbose_name=_('Event Series'),
help_text=_(u'Wenn dieser Event zu einer Veranstaltungsreihe gehört \
werden Ort, Beschreibung, Bild und Homepage von dem hier angegebenen \
Event übernommen.')
)
date_created = models.DateTimeField(
auto_now_add=True,
null=True,
db_index=True,
editable=False,
verbose_name=_('first created at'),
)
date_modified = models.DateTimeField(
auto_now=True,
editable=False,
verbose_name=_('latest updated at'),
)
objects = EventManager()
class Meta(object):
"""order the events by start date."""
verbose_name = _('Event')
verbose_name_plural = _('Events')
ordering = ('start', 'end',)
def __str__(self):
try:
return "%(name)s (%(date)s)" % {'name': self.name,
'date': self.start.date()}
except:
return "New Event Model"
def clean(self):
if self.end and self.end < self.start:
raise ValidationError({
'end': _("A event can't end before it had started")
})
def get_absolute_url(self):
kwargs = {
'pk': self.id,
'year': self.start.strftime('%Y'),
'month': self.start.strftime('%m')
}
return reverse('event-detail', kwargs=kwargs)
def get_eventseries_form_url(self):
kwargs = {
'pk': self.id,
'year': self.start.strftime('%Y'),
'month': self.start.strftime('%m')
}
return reverse('eventseries-form', kwargs=kwargs)
def get_edit_url(self):
kwargs = {
'pk': self.id,
'year': self.start.strftime('%Y'),
'month': self.start.strftime('%m')
}
return reverse('event-form', kwargs=kwargs)
def get_image(self):
if self.image:
return self.image
elif self.photo_count:
return self.photo_set.all().order_by('?')[0].image
elif self.location.image:
return self.location.image
else:
return None
@property
def is_future_event(self):
return self.start > now()
def save(self, **kwargs):
# Fülle fehlende Felder mit den Angaben der Hauptveranstaltung aus.
if self.event_series:
master_event = self.event_series
self.name = self.name or master_event.name
self.description = self.description or master_event.description
self.location = master_event.location
self.url = master_event.url
self.image = self.image or master_event.image
self.photo_count = self.photo_set.count()
super(Event, self).save(**kwargs)
# Update the Hanchans if necesery:
for hanchan in self.hanchan_set.all():
hanchan.save()
class Location(models.Model):
name = models.CharField(_("Name"), max_length=200)
description = RichTextField(_("Description"), blank=True)
image = ThumbnailerImageField(
_("Image"),
upload_to=get_upload_path,
storage=OverwriteStorage(),
blank=True,
null=True
)
url = models.URLField(_('Homepage'), blank=True)
postal_code = models.CharField(_('Postal Code'), max_length=6)
street_address = models.CharField(_('Street Address'), max_length=127)
locality = models.CharField(_('Locality'), max_length=127)
country = models.CharField(_('Country'), max_length=2, choices=COUNTRIES)
date_created = models.DateTimeField(
auto_now_add=True,
db_index=True,
editable=False,
null=True,
verbose_name=_('first created at'),
)
date_modified = models.DateTimeField(
auto_now=True,
editable=False,
verbose_name=_('latest updated at'),
)
class Meta(object):
verbose_name = _('Venue')
verbose_name_plural = _('Venues')
def __str__(self):
return self.name
@property
def address(self):
address = (self.street_address, self.locality, self.country,)
return ','.join(address)
class Photo(models.Model):
name = models.CharField(_("Name"), max_length=100, blank=True)
image = ThumbnailerImageField(
_("Image"),
upload_to=get_upload_path,
storage=OverwriteStorage()
)
event = models.ForeignKey('events.Event')
description = models.TextField(
_("Description"),
max_length=300,
blank=True
)
photographer = models.ForeignKey(settings.AUTH_USER_MODEL)
on_startpage = models.BooleanField(
_("Startpage"),
default=False,
db_index=True,
help_text=_('Display this Photo on the Startpage Teaser')
)
created_date = models.DateTimeField(_("Published on"))
views = models.PositiveIntegerField(
_("Number of views"),
editable=False,
default=0
)
date_created = models.DateTimeField(
auto_now_add=True,
db_index=True,
editable=False,
null=True,
verbose_name=_('first created at'),
)
date_modified = models.DateTimeField(
auto_now=True,
editable=False,
verbose_name=_('latest updated at'),
)
metadata = None
orientation = 1
class Meta:
get_latest_by = "created_date"
ordering = ["created_date"]
db_table = 'events_photo'
verbose_name = _('Event Image')
verbose_name_plural = _('Event Images')
def __str__(self):
return os.path.basename(self.image.name)
def rotate(self, rotate):
# TODO: Eine vernüftigte Methode ohne viele Abhängigkeiten finden um
# die Bilder bei Bedarf zu drehen.
if rotate == 'clockwise':
pass
elif rotate == 'counter-clockwise':
pass
self.save()
def save(self, **kwargs):
super(Photo, self).save(**kwargs)
self.event.save()
def get_absolute_url(self):
return reverse(
'event-photo',
kwargs={'event': self.event.id, 'pk': self.id}
)
@property
def next_photo(self):
queryset = Photo.objects.filter(created_date__gt=self.created_date)
queryset = queryset.order_by('created_date')
try:
if self.event.event_series:
return queryset.filter(
Q(event=self.event) |
Q(event=self.event.event_series) |
Q(event__event_series=self.event.event_series)
)[0]
else:
return queryset.filter(
Q(event=self.event) |
Q(event__event_series=self.event)
)[0]
except IndexError:
return None
@property
def previous_photo(self):
queryset = Photo.objects.filter(created_date__lt=self.created_date)
queryset = queryset.order_by('-created_date')
try:
if self.event.event_series:
return queryset.filter(
Q(event=self.event) |
Q(event=self.event.event_series) |
Q(event__event_series=self.event.event_series)
)[0]
else:
return queryset.filter(
Q(event=self.event) |
Q(event__event_series=self.event)
)[0]
except IndexError:
return None