django-auditlog/src/auditlog/diff.py
2015-02-16 17:06:17 +01:00

63 lines
2.2 KiB
Python

from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Model
def model_instance_diff(old, new, **kwargs):
"""
Calculate the differences between two model instances. One of the instances may be None (i.e., a newly
created model or deleted model). This will cause all fields with a value to have changed (from None).
"""
from auditlog.registry import auditlog
if not(old is None or isinstance(old, Model)):
raise TypeError('The supplied old instance is not a valid model instance.')
if not(new is None or isinstance(new, Model)):
raise TypeError('The supplied new instance is not a valid model instance.')
diff = {}
if old is not None and new is not None:
fields = set(old._meta.fields + new._meta.fields)
model_fields = auditlog.get_model_fields(new._meta.model)
elif old is not None:
fields = set(old._meta.fields)
model_fields = auditlog.get_model_fields(old._meta.model)
elif new is not None:
fields = set(new._meta.fields)
model_fields = auditlog.get_model_fields(new._meta.model)
else:
fields = set()
model_fields = None
# Check if fields must be filtered
if model_fields and (model_fields['include_fields'] or model_fields['exclude_fields']) and fields:
filtered_fields = []
if model_fields['include_fields']:
filtered_fields = [field for field in fields
if field.name in model_fields['include_fields']]
else:
filtered_fields = fields
if model_fields['exclude_fields']:
filtered_fields = [field for field in filtered_fields
if field.name not in model_fields['exclude_fields']]
fields = filtered_fields
for field in fields:
try:
old_value = unicode(getattr(old, field.name, None))
except ObjectDoesNotExist:
old_value = None
try:
new_value = unicode(getattr(new, field.name, None))
except ObjectDoesNotExist:
new_value = None
if old_value != new_value:
diff[field.name] = (old_value, new_value)
if len(diff) == 0:
diff = None
return diff