Source code for superdjango.db.audit.models

# Imports

from django.conf import settings
from django.db import models
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
from superdjango.shortcuts import get_user_name
from ..datetime.fields import AutoNowAddDateTimeField, AutoNowDateTimeField
from .mixins import AuditMixin

# Exports

__all__ = (
    "AddedByModel",
    "ModifiedByModel",
    "ViewedByModel",
)

# Constants

AUTH_USER_MODEL = settings.AUTH_USER_MODEL

# Models


[docs]class AddedByModel(AuditMixin, models.Model): """Tracks the user that added a record as well as the date and time the record was created. **Fields** This class will add the following fields: - ``added_by`` The user that added the record. - ``added_dt`` The date and time the record was added. **Proper Name** The ``added_by_name`` property is also provided which attempts to return the full name of the user. **Implementation** .. code-block:: py class Project(AddedByModel): # ... class Meta: get_latest_by = "added_dt" ordering = ["-added_dt"] """ # blank must be True to allow form submission. added_by = models.ForeignKey( AUTH_USER_MODEL, blank=True, on_delete=models.PROTECT, related_name="%(app_label)s_%(class)s_added_records", verbose_name=_("added by") ) added_dt = AutoNowAddDateTimeField( _("added date/time"), help_text=_("Date and time the record was created.") ) class Meta: abstract = True
[docs] def audit(self, user, commit=True): """Check for ``added_by_id`` just in case the primary key is being managed at run time. A ``RelatedObjectDoesNotExist`` error will be thrown if we just look for ``added_by``, so the simplest thing to do appears to be checking for the primary key instead. """ # noinspection PyUnresolvedReferences if not self.pk or not self.added_by_id: self.added_by = user super().audit(user, commit=commit)
@property def added_by_name(self): """Get the full name or user name of the user that added the record. :rtype: str """ return get_user_name(self.added_by)
[docs]class ModifiedByModel(AuditMixin): """Tracks the user that last updated a record as well as the date and time of the last update. **Fields** This class will add the following fields: - ``modified_by`` The user that modified record. - ``modified_dt`` The date and time the modified was added. **Proper Name** The ``modified_by_name`` property is also provided which attempts to return the full name of the user. **Implementation** .. code-block:: py class MyModel(ModifiedByModel): # ... class Meta: ordering = ["modified_dt"] """ # blank must be True to allow form submission modified_by = models.ForeignKey( AUTH_USER_MODEL, blank=True, on_delete=models.PROTECT, related_name="%(app_label)s_%(class)s_modified_records", verbose_name=_("modified by") ) modified_dt = AutoNowDateTimeField( _("modified date/time"), help_text=_("Date and time the record was last modified.") ) class Meta: abstract = True
[docs] def audit(self, user, commit=True): """Always sets ``modified_by`` to the given user.""" self.modified_by = user super().audit(user, commit=commit)
@property def modified_by_name(self): """Get the full name or user name of the user that last modified the record. :rtype: str """ return get_user_name(self.modified_by)
[docs]class ViewedByModel(AuditMixin): """Tracks the user that view a record as well as the date and time the record was last viewed. **Fields** This class will add the following fields: - ``viewed_by`` The user that viewed record. - ``viewed_dt`` The date and time the record was last viewed. **Proper Name** The ``viewed_by_name`` property is also provided which attempts to return the full name of the user. **Implementation** .. code-block:: python class MedicalRecord(ViewedByModel): # ... """ viewed_by = models.ForeignKey( AUTH_USER_MODEL, blank=True, null=True, on_delete=models.SET_NULL, related_name="%(app_label)s_%(class)s_viewed_records", verbose_name=_("viewed by") ) viewed_dt = models.DateTimeField( _("viewed date/time"), blank=True, help_text=_("Date and time the record was last viewed."), null=True ) class Meta: abstract = True
[docs] def audit(self, user, commit=True): """Update viewed fields. .. important:: This method makes calls to ``super()`` which may also trigger the update of other fields if the model also extends :py:class:`AddedByModel` or :py:class:`ModifiedByModel`. See ``mark_viewed()`` if you just want to update the ``viewed_by`` and ``viewed_dt`` fields. """ self.viewed_by = user self.viewed_dt = now() super().audit(user, commit=commit)
[docs] def mark_viewed(self, user, commit=True): """Mark the record as viewed. :param user: The user that reviewed the record. :type user: AUTH_USER_MODEL :param commit: Indicates the record should be saved after updating the field. :type commit: bool """ self.viewed_by = user self.viewed_dt = now() if commit: self.save(update_fields=["viewed_by", "viewed_dt"])
[docs] def mark_unviewed(self, commit=True): """Mark the record as "un-viewed", removing the last viewed data. :param commit: Indicates the record should be saved after updating the field. :type commit: bool """ self.viewed_by = None self.viewed_dt = None if commit: self.save(update_fields=["viewed_by", "viewed_dt"])
@property def viewed_by_name(self): """Get the full name or user name of the user that last viewed the record. :rtype: str """ return get_user_name(self.viewed_by)