Skip to content

Instantly share code, notes, and snippets.

@gepatino
Created May 11, 2017 17:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gepatino/c444a309014943d3b0292eeb30e87354 to your computer and use it in GitHub Desktop.
Save gepatino/c444a309014943d3b0292eeb30e87354 to your computer and use it in GitHub Desktop.
Field change aware Django Model
from django.db import models
class StoredOriginalValuesModel(models.Model):
"""
Model that stores original data in a dictionary and provides the
field_has_changed(field_name) method to check if a field has been modified
after loading the data from the db.
Original values are stored in the _original dictionary only when creating
the object or calling refresh_from_db(), so the field_has_changed() method
works even after save().
"""
class Meta:
abstract = True
def __init__(self, *args, **kwargs):
super(StoredOriginalValuesModel, self).__init__(*args, **kwargs)
self.store_original_values()
def refresh_from_db(self, *args, **kwargs):
super(StoredOriginalValuesModel, self).refresh_from_db(*args, **kwargs)
self.store_original_values()
def store_original_values(self):
"""
Store the current model data as original values.
"""
all_fields = self._meta.get_fields(include_parents=True)
# TODO: check how to store ForeingKeys and ManyToManys
fields = [x for x in all_fields if not x.is_relation]
self._original = {}
for field in fields:
self._original[field.name] = field.value_from_object(self)
def field_has_changed(self, field):
"""
Verifies if a field was changed since last refresh from db.
"""
if field not in self._original:
raise Exception('Field not found in stored original values: %s' % field)
return self._original[field] != getattr(self, field)
def changed_fields(self):
"""
Returns a list of all changed fields.
"""
changed_fields = []
for field in self._original.keys():
if self.field_has_changed(field):
changed_fields.append(field)
return changed_fields
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment