Подтвердить что ты не робот

Django - проверка различия между старым и новым значением при переопределении метода сохранения

спасибо за ваше время.

Я на Django 1.4, и у меня есть следующий код: его метод save для моей модели Quest.

@commit_on_success
def save(self, *args, **kwargs):
    from ib.quest.models.quest_status_update import QuestStatusUpdate
    created = not self.pk

    if not created:
        quest = Quest.objects.get(pk=self)
        # CHECK FOR SOME OLD VALUE
    super(Quest, self).save(*args, **kwargs)

Я не мог найти разумный способ сделать это. Мне кажется очень глупым сделать новый запрос для объекта, который я сейчас обновляю, чтобы узнать старое значение экземпляра.

Есть ли лучший способ сделать это?

Спасибо всем.

Франциско

4b9b3361

Ответ 1

Вы можете сохранить старое значение внутри метода init:

def __init__(self, *args, **kwargs):
    super(MyModel, self).__init__(*args, **kwargs)
    self.old_my_field = self.my_field

def save(self, *args, **kwargs):
    print self.old_my_field
    print self.my_field

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

Ответ 2

Django не кэширует старые значения экземпляра модели, поэтому вам нужно сделать это самостоятельно или выполнить другой запрос перед сохранением.

Один общий шаблон - использовать сигнал предварительного сохранения (или поместить этот код непосредственно в свой метод save(), как вы это сделали):

old_instance = MyModel.objects.get(pk=instance.pk)
# compare instance with old_instance, and maybe decide whether to continue

Если вы хотите сохранить кеш старых значений, вы, вероятно, сделаете это в своем коде зрения:

from copy import deepcopy
object = MyModel.objects.get(pk=some_value)
cache = deepcopy(object)

# Do something with object, and then compare with cache before saving

Недавно было обсуждено обсуждение django-разработчиков об этом, а также некоторые другие возможные решения.

Ответ 3

Я проверяю разницу на старые значения, используя сигнал django-reversion, но та же логика применима к сигналам сохранения. Разница для меня в том, что я хочу сохранить, было ли поле сохранено или нет.

@receiver(reversion.pre_revision_commit)
def it_worked(sender, **kwargs):
    currentVersion = kwargs.pop('versions')[0].field_dict
    fieldList = currentVersion.keys()
    fieldList.remove('id')
    commentDict = {}
    print fieldList
    try:
        pastVersion = reversion.get_for_object(kwargs.pop('instances')[0])[0].field_dict
    except IndexError:
        for field in fieldList:
            commentDict[field] = "Created"
        comment = commentDict
    except TypeError:
        for field in fieldList:
            commentDict[field] = "Deleted"
        comment = commentDict
    else:
        for field in fieldList:
            try:
                pastTest = pastVersion[field]
            except KeyError:
                commentDict[field] = "Created"
            else:       
                if currentVersion[field] != pastTest:
                    commentDict[field] = "Changed"
                else:
                    commentDict[field] = "Unchanged"
        comment = commentDict
    revision = kwargs.pop('revision')
    revision.comment = comment
    revision.save()
    kwargs['revision'] = revision
    sender.save_revision