Отслеживание изменений начиная с последнего сохранения в django моделях

Пару раз я столкнулся с ситуацией, когда в экономят время, я должен знать, какие образцовые поля будут обновленными и действие соответственно.

Самое очевидное решение этого состоит в том, чтобы взять поле первичного ключа и получить копию модели от базы данных:

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.

Возможно, кто-то знает более чистый способ сделать это?

9
задан shylent 9 January 2010 в 22:02
поделиться

1 ответ

Я думаю, что ваше решение выглядит разумно.

В качестве альтернативы вы можете иметь метод менеджера под названием Get_And_Copy () (или что-то), что повесило копию исходного объекта от того, что возвращается. Затем вы можете использовать другой метод менеджера SAVE_AND_CHECK () , который воспользовался скопированным оригиналом.

FWIW: Если вы играете с шаблонами Adva / Admin, существует контекстная переменная Оригинал , которая является копией исходного объекта.

Обновление: Я посмотрел более внимательно на том, что делает админ. В Class ModelAdmin (Расположенный в Django / App / admin / options.py) Существует метод, называемый Contruct_Change_Message () . Он приводится в движение pormset.Changed_data и pormset.Changed_Objects , поэтому django / forms / model.py Базовый класс - это то, где действие. Смотрите метод SAVE_EXISTING_OBJECTS () . Также посмотрите на метод _Existing_Object () . Это немного сложнее, чем то, что я упоминал ранее, потому что они имеют дело с возможностью нескольких объектов, но в основном они кэшируют результаты запроса на первый доступ.

2
ответ дан 5 December 2019 в 02:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: