Source code for superdjango.db.history.utils

# Exports

__all__ = (
    "get_field_changes",
    "FieldChange",
)

# Functions


[docs]def get_field_changes(form, model, record=None): """Get the changed fields for a given form and record. :param form: The validated form instance. :param model: The model class represented by the record. :param record: The current record instance. It is safe to pass ``None``. :rtype: list[superdjango.db.history.utils.FieldChange] :returns: A list pf changed fields when record is not ``None``. Otherwise, an empty list. """ # It's possible at runtime that a form instance is None. If so, there's nothing to compare and we don't want to # raise an error because we will assume it's intentional. if form is None: return list() # We might not have received a record, for example if this is a create operation. So again, don't raise an error. if record is None: return list() # Get the existing data. old_record = model.objects.get(pk=record.pk) # Compare old data with submitted data. changes = list() # noinspection PyProtectedMember for field in model._meta.get_fields(): if field.name in form.cleaned_data: old_value = getattr(old_record, field.name) if old_value != form.cleaned_data[field.name]: change = FieldChange(field.name, form.cleaned_data[field.name], old_value, label=field.verbose_name) changes.append(change) # Return the change instances. return changes
# Classes
[docs]class FieldChange(object): """Wraps the change that has occurred to a given field."""
[docs] def __init__(self, field_name, new_value, old_value, label=None): """Initialize a field change. :param field_name: The name of the field that was changed. :type field_name: str :param new_value: The new value, e.g. from the cleaned data of a form. :param old_value: The existing value from the database prior to save. :param label: The field label (verbose name). :type label: str """ self.field_label = label or field_name.replace("_", " ") self.field_name = field_name self.new_value = new_value self.old_value = old_value
def __repr__(self): return "<%s %s: %s -> %s>" % (self.__class__.__name__, self.field_name, self.old_value, self.new_value) def __str__(self): return "%s: %s -> %s" % (self.field_label, self.old_value, self.new_value)