Browse Source

Abstract workflow models.

master
Erik Stein 3 years ago
parent
commit
c8b5c62a43
  1. 123
      shared/utils/models/workflow.py

123
shared/utils/models/workflow.py

@ -0,0 +1,123 @@
from django.conf import settings
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
#
# Workflow Helpers
"""
States:
- inactive (either active=False or publication date not reached)
- public (active or archived)
- active (public, not archived)
- archived (public, not active)
"""
class WorkflowQuerySet(models.QuerySet):
@classmethod
def exclude_inactive_filter(cls):
"""Usage: qs.exclude(**self.exclude_inactive_filter())"""
return {
"is_published": True,
"publication_datetime__lte": timezone.now().date(),
}
@classmethod
def active_filter(cls):
return {
"is_published": True,
"publication_datetime__lte": timezone.now().date(),
"archiving_datetime__gte": timezone.now().date(),
}
@classmethod
def archived_filter(cls):
return {
"is_published": True,
"publication_datetime__lte": timezone.now().date(),
"archiving_datetime__lte": timezone.now().date(),
}
def public(self):
# Active or archived
return self.exclude(**self.exclude_inactive_filter())
def active(self):
return self.filter(**self.active_filter())
def archived(self):
return self.filter(**self.archived_filter())
class ManyToManyWorkflowQuerySet(WorkflowQuerySet):
def _build_related_filters(self, filter_template):
"""
Transforms all filter rules to match any related models which
itself is workflow managed.
"""
filter = {}
for field in self.model._meta.get_fields():
if field.many_to_one and isinstance(field.related_model._meta.default_manager, WorkflowManager):
field.name
for path, value in filter_template.items():
filter[f'{field.name}__{path}'] = value
return filter
def public(self):
# Active or archived
return self.exclude(**self._build_related_filters(self.exclude_inactive_filter()))
def active(self):
return self.filter(**self._build_related_filters(self.active_filter()))
def archived(self):
return self.filter(**self._build_related_filters(self.archived_filter()))
class WorkflowManager(models.Manager.from_queryset(WorkflowQuerySet)):
pass
class ManyToManyWorkflowManager(models.Manager.from_queryset(ManyToManyWorkflowQuerySet)):
pass
class WorkflowMixin(models.Model):
creation_datetime = models.DateTimeField(auto_now_add=True)
modification_datetime = models.DateTimeField(auto_now=True)
creation_user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True,
editable=False,
on_delete=models.SET_NULL, related_name='+')
modification_user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True,
editable=False,
on_delete=models.SET_NULL, related_name='+')
is_published = models.BooleanField(_("Publicly visible"), default=False)
publication_datetime = models.DateTimeField(_("Publication Date"), default=timezone.now)
archiving_datetime = models.DateTimeField(_("Archiving Date"), default=timezone.datetime.max)
objects = WorkflowManager()
class Meta:
abstract = True
ordering = ['-publication_datetime'] # Most recent first
@property
def worflow_status(self):
now = timezone.now()
if not self.is_active or self.publication_datetime < now:
return 'inactive'
elif self.publication_datetime >= now and self.archiving_datetime < now:
return 'active'
else:
return 'archived'
def display_is_active(obj):
return obj.is_publised and obj.publication_datetime <= timezone.now()
display_is_active.boolean = True
display_is_active.short_description = _("Aktiv")
Loading…
Cancel
Save