Source code for dcolumn.common.model_mixins
# -*- coding: utf-8 -*-
#
# dcolumn/common/model_mixins.py
#
"""
Mixins used in Django models.
"""
__docformat__ = "restructuredtext en"
import re
import logging
from datetime import datetime
from dateutil.tz import tzutc
from django.db import models
from django.db.models import Q
from django.utils.translation import gettext_lazy as _
from django.conf import settings
from dcolumn.common import ChoiceManagerImplementation
log = logging.getLogger('dcolumns.common.model_mixins')
#
# UserModel
#
[docs]class UserModelMixin(models.Model):
"""
Abstract model mixin used in the model classes to provide user and
creator fields.
"""
updater = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
verbose_name=_("Updater"), editable=False,
related_name="%(app_label)s_%(class)s_updater_related",
help_text=_("The last user to update this record."))
creator = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
verbose_name=_("Creator"), editable=False,
related_name="%(app_label)s_%(class)s_creator_related",
help_text=_("The user who created this record."))
[docs] def save(self, *args, **kwargs):
"""
Save is here to assure that save is executed throughout the MRO.
:param args: Positional arguments.
:param kwargs: Keyword arguments.
"""
super(UserModelMixin, self).save(*args, **kwargs)
[docs] def updater_producer(self):
"""
Primary use is in an admin class to supply the updater's full name if
available else the username.
:rtype: String of updater's full name.
"""
result = self.updater.get_full_name()
if not result:
result = self.updater.username
return result
updater_producer.short_description = _("Updater")
[docs] def creator_producer(self):
"""
Primary use is in an admin class to supply the creator's full name if
available else the username.
:rtype: String of creator's full name.
"""
result = self.creator.get_full_name()
if not result:
result = self.creator.username
return result
creator_producer.short_description = _("Creator")
#
# TimeModel
#
[docs]class TimeModelMixin(models.Model):
"""
Abstract model mixin used in the model classes to supply created and
updated fields.
"""
created = models.DateTimeField(
verbose_name=_("Date Created"),
help_text=_("The date and time of creation."))
updated = models.DateTimeField(
verbose_name=_("Last Updated"),
help_text=_("The date and time last updated."))
[docs] def save(self, *args, **kwargs):
"""
Understands two keyword arguments, ``disable_created`` and
``disable_updated``. These arguments are used to optionally turn off
the updating of the ``created`` and ``updated`` fields on the model.
This can be used when migrating data into a model that already has
these fields set so the original date ad times can be kept.
:param args: Positional arguments.
:param kwargs: Keyword arguments.
"""
if not kwargs.pop('disable_created', False) and self.created is None:
self.created = datetime.now(tzutc())
if not kwargs.pop('disable_updated', False):
self.updated = datetime.now(tzutc())
log.debug("kwargs: %s, created: %s, updated: %s",
kwargs, self.created, self.updated)
super(TimeModelMixin, self).save(*args, **kwargs)
#
# StatusModel
#
[docs]class StatusModelManagerMixin(models.Manager):
"""
Manager mixin for the StatusModelMixin abstract model.
"""
[docs] def active(self, active=True):
"""
Return as default only active database objects.
:param active: If ``True`` return only active records else if ``False``
return non-active records. If ``None`` return all
records.
:type active: bool
:rtype: Django query results.
"""
query = []
if active is not None:
query.append(Q(active=active))
return self.filter(*query)
[docs]class StatusModelMixin(models.Model):
"""
Abstract model mixin used in the model classes to supply the active field.
"""
active = models.BooleanField(
verbose_name=_("Active"), default=True,
help_text=_("If checked the record is active."))
[docs] def save(self, *args, **kwargs):
"""
Save is here to assure that save is executed throughout the MRO.
:param args: Positional arguments.
:param kwargs: Keyword arguments.
"""
super(StatusModelMixin, self).save(*args, **kwargs)
#
# ValidateOnSaveMixin
#
[docs]class ValidateOnSaveMixin(models.Model):
[docs] def save(self, *args, **kwargs):
"""
Execute ``full_clean``.
:param args: Positional arguments.
:param kwargs: Keyword arguments.
"""
self.full_clean()
super(ValidateOnSaveMixin, self).save(*args, **kwargs)