I've got a code like that:
# ... obj = Model.objects.get(pk=2342) if foo: obj.foo = 'bar' if bar: obj.bar = 'baz' obj.save() Is there a good way to find out if the model instance was modified in order to prevent saving it each time the code runs?
Just diff the 'snapshot' instance w/ current model instance field-by-field, you could get the snapshot through copy.copy(obj) or model_cls.objects.get(pk=obj.pk).
Also you could simply compare the dumped versions:
from django.core.serializers.json import Serializer dump = Serializer.serialize([obj]) ... changed = dump == Serializer.serialize([obj]) Normally, tweak your code is easiest:
obj = Model.objects.get(pk=2342) # 'obj' is better than 'model', IMO changed = False if foo: ... obj.foo = 'bar' changed = True if bar: ... obj.bar = 'baz' changed = True if changed: obj.save() Django performs this check internally. An sql query wont be fired unless the model has actually changed.
UPDATE
This answer is wrong. My bad. I confused this with something else.
has_changed checking of the Django form?To do this in a more abstracted way, look at the documentation for the model method from_db(), which is a hook called when data is loaded into the model instance from the database. With this method, you can cache the original value of a field as it is loaded, and then compare that to the current value in the save() method.
Example (note, I haven't actually tested this code):
class SaveIfModified(models.Model): foo = models.TextField() @classmethod def from_db(cls, db, field_names, values): instance = super().from_db(db, field_names, values) # caveat: deferred values won't appear here if "foo" in field_names: instance._foo = values[field_names.index("foo")] return instance def save(self, *args, **kwargs): if self.foo == getattr(self, "_foo", None): return super().save(*args, **kwargs)