From 3346a8e15b6015e0409ae960b0e22d579771b544 Mon Sep 17 00:00:00 2001 From: Erik Stein Date: Mon, 27 Aug 2018 15:52:03 +0200 Subject: [PATCH] Added RuntimeMixin. --- shared/utils/models/events.py | 114 ++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 shared/utils/models/events.py diff --git a/shared/utils/models/events.py b/shared/utils/models/events.py new file mode 100644 index 0000000..8ba820f --- /dev/null +++ b/shared/utils/models/events.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import datetime + +from django.conf import settings +from django.core.exceptions import ValidationError +from django.db import models +from django.utils.translation import ugettext_lazy as _ + +from shared.utils.dateformat import format_partial_date, format_date_range + + +USE_TRANSLATABLE_FIELDS = getattr(settings, 'CONTENT_USE_TRANSLATABLE_FIELDS', False) +# TODO Implement translatable AutoSlugField: USE_TRANSLATABLE_SLUG_FIELDS = getattr(settings, 'CONTENT_USE_TRANSLATABLE_SLUG_FIELDS', True) + +if USE_TRANSLATABLE_FIELDS: + from shared.multilingual.utils.fields import TranslatableCharField +else: + TranslatableCharField = models.CharField + + +# FIXME Currently Python cannot handle BC dates +# Possibly solution: https://github.com/okfn/datautil/blob/master/datautil/date.py +MIN_DATE = datetime.date.min +MAX_DATE = datetime.date.max + + +class RuntimeMixin(models.Model): + """Allows a model to have partially defined from-/to-dates; + at least one year value must be entered. + """ + from_year_value = models.PositiveIntegerField(_("starting year"), null=True, blank=True) + from_month_value = models.PositiveIntegerField(_("starting month"), null=True, blank=True) + from_day_value = models.PositiveIntegerField(_("starting day"), null=True, blank=True) + _from_sort_date = models.DateField(_("from"), editable=False) + until_year_value = models.PositiveIntegerField(_("ending year"), null=True, blank=True) + until_month_value = models.PositiveIntegerField(_("ending month"), null=True, blank=True) + until_day_value = models.PositiveIntegerField(_("ending day"), null=True, blank=True) + _until_sort_date = models.DateField(_("until"), editable=False) + + runtime_text = TranslatableCharField(_("Zeitangabe Textform"), + max_length=200, null=True, blank=True, + help_text=_("Alternativer Text für die Laufzeitangabe")) + + class Meta: + abstract = True + + def clean(self): + if not (self.from_year_value or self.until_year_value): + raise ValidationError(_('Please enter either a from or an until date year.')) + + # Update from/sort date fields + if self.from_year_value: + self._from_sort_date = datetime.date( + self.from_year_value, self.from_month_value or 1, self.from_day_value or 1) + else: + self._from_sort_date = MIN_DATE + + if self.until_year_value: + self._until_sort_date = datetime.date( + self.until_year_value, self.until_month_value or 12, self.until_day_value or 31) + else: + self._until_sort_date = MAX_DATE + + def save(self, *args, **kwargs): + self.full_clean() + super(RuntimeMixin, self).save(*args, **kwargs) + + @property + def from_date(self): + return self._from_sort_date + + @property + def until_date(self): + return self._until_sort_date + + # TODO Implement @fron_date.setter, @until_date.setter + + def get_from_display(self): + return self.runtime_text or format_partial_date( + self.from_year_value, + self.from_month_value, + self.from_day_value) + get_from_display.admin_order_field = '_from_sort_date' + get_from_display.short_description = _("from") + + def get_until_display(self): + if self.runtime_text: + return "" + else: + return format_partial_date( + self.until_year_value, + self.until_month_value, + self.until_day_value) + get_until_display.admin_order_field = '_until_sort_date' + get_until_display.short_description = _("until") + + def get_runtime_display(self): + # TODO Improve + if not self.runtime_text and \ + self.from_day_value and self.from_month_value: + return format_date_range(self._from_sort_date, self._until_sort_date) + else: + f = self.get_from_display() + # Single point + if self._from_sort_date == self._until_sort_date: + return f + + u = self.get_until_display() + if f and u: + return "{}–{}".format(f, u) + else: + return f or u