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# Exports
3__all__ = (
4 "get_field_changes",
5 "FieldChange",
6)
8# Functions
11def get_field_changes(form, model, record=None):
12 """Get the changed fields for a given form and record.
14 :param form: The validated form instance.
16 :param model: The model class represented by the record.
18 :param record: The current record instance. It is safe to pass ``None``.
20 :rtype: list[superdjango.db.history.utils.FieldChange]
21 :returns: A list pf changed fields when record is not ``None``. Otherwise, an empty list.
23 """
24 # It's possible at runtime that a form instance is None. If so, there's nothing to compare and we don't want to
25 # raise an error because we will assume it's intentional.
26 if form is None:
27 return list()
29 # We might not have received a record, for example if this is a create operation. So again, don't raise an error.
30 if record is None:
31 return list()
33 # Get the existing data.
34 old_record = model.objects.get(pk=record.pk)
36 # Compare old data with submitted data.
37 changes = list()
38 # noinspection PyProtectedMember
39 for field in model._meta.get_fields():
40 if field.name in form.cleaned_data:
41 old_value = getattr(old_record, field.name)
42 if old_value != form.cleaned_data[field.name]:
43 change = FieldChange(field.name, form.cleaned_data[field.name], old_value, label=field.verbose_name)
44 changes.append(change)
46 # Return the change instances.
47 return changes
49# Classes
52class FieldChange(object):
53 """Wraps the change that has occurred to a given field."""
55 def __init__(self, field_name, new_value, old_value, label=None):
56 """Initialize a field change.
58 :param field_name: The name of the field that was changed.
59 :type field_name: str
61 :param new_value: The new value, e.g. from the cleaned data of a form.
63 :param old_value: The existing value from the database prior to save.
65 :param label: The field label (verbose name).
66 :type label: str
68 """
69 self.field_label = label or field_name.replace("_", " ")
70 self.field_name = field_name
71 self.new_value = new_value
72 self.old_value = old_value
74 def __repr__(self):
75 return "<%s %s: %s -> %s>" % (self.__class__.__name__, self.field_name, self.old_value, self.new_value)
77 def __str__(self):
78 return "%s: %s -> %s" % (self.field_label, self.old_value, self.new_value)