Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
3Abstract
4--------
6The history package provides an abstract model for implementing a log of historical activity on other models. For a
7practical implementation, see ``superdjango.contrib.history``.
9Usage
10-----
12Implementing Audit History
13..........................
15You may create your own history by extending :py:class:`superdjango.db.history.models.HistoryModel`.
17.. code-block:: python
19 # myapp/models.py
20 from superdjango.db.history.models import HistoryModel
22 class History(HistoryModel):
24 class Meta:
25 get_latest_by = "added_dt"
26 ordering = ["-added_dt"]
27 verbose_name = _("Log Entry")
28 verbose_name_plural = _("Log Entries")
30See the ``admin`` and ``ui`` modules of this package for implementing Django Admin and SuperDjango UI user interfaces.
32Creating an Audit Trail
33.......................
35Your view must call the ``log`` method:
37.. code-block:: python
39 # myapp/views.py
40 from .models import History
42 class CreateTodo(CreateView):
43 ...
45 def form_valid(self, form):
46 self.object = form.save()
48 History.log(self.object, self.request.user, History.CREATE)
50 ...
52Tracking Changes to Fields
53..........................
55The :py:class:`superdjango.db.history.utils.FieldChange` may be used to assist with tracking changes to fields. The
56:py:func:`superdjango.db.history.utils.get_field_changes` is also provided as a shortcut for creating ``FieldChange``
57instances.
59.. code-block:: python
61 # myapp/models.py
62 from superdjango.db.history.models import HistoryModel
64 class History(HistoryModel):
66 field_changes = models.TextField(
67 blank=True,
68 null=True
69 )
71 class Meta:
72 get_latest_by = "added_dt"
73 ordering = ["-added_dt"]
74 verbose_name = _("Log Entry")
75 verbose_name_plural = _("Log Entries")
77 @classmethod
78 def log_field_changes(cls, instance, verb, fields=None):
79 if fields is None:
80 return
82 a = list()
83 for change in fields:
84 a.append(str(change))
86 instance.field_changes = "\\n".join(a)
88 # myapp/views.py
89 from superdjango.db.history.utils import get_field_changes
90 from .models import History
92 class UpdateTodo(UpdateView):
93 ...
95 def form_valid(self, form):
96 self.object = form.save()
98 field_changes = get_field_changes(form, self.model, record=self.object)
100 History.log(self.object, self.request.user, History.UPDATE, fields=field_changes)
102 ...
104You could also implement a separate model to record each field change and connect it to the history record.
106.. code-block:: python
108 # myapp/models.py
109 from superdjango.db.history.models import HistoryModel
111 class History(HistoryModel):
112 ...
114 @classmethod
115 def log_field_changes(cls, instance, verb, fields=None):
116 if fields is None:
117 return
119 a = list()
120 for change in fields:
121 field_history = FieldHistory(
122 field_label=change.field_label,
123 field_name=change.field_name
124 history=instance,
125 new_value=change.new_value,
126 old_value=change.old_value,
127 )
128 field_history.save()
130 class FieldHistory(models.Model):
132 field_label = models.CharField(
133 max_length=256
134 )
136 field_name = models.CharField(
137 max_length=256
138 )
140 history = models.ForeignKey(
141 History,
142 on_delete=models.CASCADE,
143 related_name="field_changes",
144 verbose_name=_("History")
145 )
147 new_value = models.TextField(
148 blank=True,
149 null=True
150 )
152 old_value = models.TextField(
153 blank=True,
154 null=True
155 )
157 class Meta:
158 ordering = ["field_label"]
159 verbose_name = _("Field History")
160 verbose_name_plural = _("Field Histories")
162 def __str__(self):
163 return "%s: %s -> %s" % (self.field_label, self.old_value, self.new_value)
166Note that custom views or UI would be required to display the field history records.
168"""
169__author__ = "Shawn Davis <shawn@superdjango.com>"
170__maintainer__ = "Shawn Davis <shawn@superdjango.com>"
171__version__ = "0.7.0-p"