# Imports
from django.conf import settings
from django.db import models
from django.utils.translation import ugettext_lazy as _
from superdjango.db.audit.utils import is_audit_model
from superdjango.shortcuts import copy_model_instance
# Exports
__all__ = (
"RevisedModel",
)
# Constants
AUTH_USER_MODEL = settings.AUTH_USER_MODEL
# Models
[docs]class RevisedModel(models.Model):
"""Supports records with revisions."""
is_previous_revision = models.BooleanField(
_("previous revision"),
default=False,
help_text=_("Indicates this is a previous revision.")
)
previous_revision = models.ForeignKey(
'self',
blank=True,
help_text=_("The last or previous version of the record."),
null=True,
on_delete=models.SET_NULL,
related_name="%(app_label)s_%(class)s_previous_revisions",
verbose_name=_("previous revision")
)
revision_by = models.ForeignKey(
AUTH_USER_MODEL,
blank=True,
help_text=_("The user that created the revision."),
null=True,
on_delete=models.SET_NULL,
related_name="%(app_label)s_%(class)s_revised_records",
verbose_name=_("revision by")
)
revision_dt = models.DateTimeField(
_("revision date/time"),
blank=True,
help_text=_("Date and time the revision was created."),
null=True
)
revision_number = models.IntegerField(
_("revision number"),
default=1,
help_text=_("The revision number for the record.")
)
class Meta:
abstract = True
# noinspection PyUnresolvedReferences
[docs] def save_revision(self, user, commit=True):
"""Save a revision of the model.
:param user: The user creating the revision.
:type user: AUTH_USER_MODEL
:param commit: Whether to save immediately.
:type commit: bool
.. tip::
The original instance is also not saved when ``commit`` is ``False``.
.. warning::
Related records are *not* changed or duplicated during the revision.
:returns: The revised record (model instance).
"""
# Create a new instance. This becomes the latest revision.
new_instance = copy_model_instance(self)
# Set attributes on the new instance.
new_instance.previous_version = self
new_instance.revision_by = user
new_instance.revision_dt = now()
# Increment the revision number.
# noinspection PyTypeChecker
new_instance.revision_number = self.revision_number + 1
# Set attributes on this instance.
self.is_previous_revision = True
# Save the new instance and the current instance as archived.
if is_audit_model(self):
self.audit(user, commit=commit)
new_instance.audit(commit=commit)
if commit:
self.save()
new_instance.save()
return new_instance