Пару раз я сталкивался с ситуацией, когда во время сохранения мне нужно знать, какие поля модели будут обновлены, и действовать соответственно.
Наиболее очевидным решением этого является использование поля первичного ключа и получение копии модели из базы данных:
class MyModel(models.Model):
def save(self, force_insert=False, force_update=False, using=None):
if self.id is not None:
unsaved_copy = MyModel.objects.get(id=self.id)
# Do your comparisons here
super(MyModel, self).save(force_insert, force_update, using)
Это прекрасно работает, однако, оно попадает в базу данных для каждого экземпляра модели, которую вы сохраняете (может быть довольно неудобно, если вы делаете много таких сохранений).
Очевидно, что если кто-то может «запомнить» старые значения полей в начале времени жизни экземпляра модели (__init__
), не должно быть необходимости получать копию модели из базы данных. Итак, я придумал этот маленький взломать:
class MyModel(models.Model):
def __init__(self, *args, **kwargs):
super(MyModel, self).__init__(*args, **kwargs)
self.unsaved = {}
for field in self._meta.fields:
self.unsaved[field.name] = getattr(self, field.name, None)
def save(self, force_insert=False, force_update=False, using=None):
for name, value in self.unsaved.iteritems():
print "Field:%s Old:%s New:%s" % (name, value, getattr(self, name, None))
# old values can be accessed through the self.unsaved member
super(MyModel, self).save(force_insert, force_update, using)
Кажется, что это работает, но использует закрытый интерфейс django.db.models.Model
.
Возможно, кто-то знает более чистый способ сделать это?