Какова наилучшая / правильная идиома в django для изменения поля во время .save (), где вам нужно старое значение? - PullRequest
1 голос
/ 16 апреля 2010

скажи, что у меня есть:

class LogModel(models.Model):
    message = models.CharField(max_length=512)

class Assignment(models.Model):
    someperson = models.ForeignKey(SomeOtherModel)
    def save(self, *args, **kwargs):
        super(Assignment, self).save()
        old_person = #?????
        LogModel(message="%s is no longer assigned to %s"%(old_person, self).save()
        LogModel(message="%s is now assigned to %s"%(self.someperson, self).save()

Моя цель - сохранить в LogModel несколько сообщений о том, кому было назначено назначение. Обратите внимание, что мне нужно знать старое, предварительно сохраненное значение этого поля.

Я видел код, который предлагает перед super (). Save () извлечь экземпляр из базы данных через первичный ключ и получить оттуда старое значение. Это может сработать, но немного грязно.

Кроме того, я планирую в конечном итоге разделить этот код из метода .save () с помощью сигналов, а именно pre_save () и post_save (). Попытка использовать вышеупомянутую логику (извлечь из базы данных в pre_save, сделать запись в журнале в post_save), по-видимому, здесь терпит неудачу, так как pre_save и post_save - два отдельных метода. Возможно, в pre_save я смогу извлечь старое значение и вставить его в модель в качестве атрибута?

Мне было интересно, была ли для этого общая идиома. Благодаря.

Ответы [ 3 ]

1 голос
/ 16 апреля 2010

Пару месяцев назад я нашел где-то в Интернете хороший способ сделать это ...

class YourModel(models.Model):

    def __init__(self, *args, **kwargs):
        super(YourModel, self).__init__(*args, **kwargs)
        self.original = {}
        id = getattr(self, 'id', None)

        for field in self._meta.fields:
            if id:
                self.original[field.name] = getattr(self, field.name, None)
            else:
                self.original[field.name] = None

В основном копия полей модели будет сохранена в self.original. Вы можете получить к нему доступ в другом месте модели ...

def save(self, *args, **kwargs):
    if self.original['my_property'] != self.my_property:
        # ...
0 голосов
/ 16 апреля 2010

Итак, я придумал это:

class LogModel(models.Model):
    message = models.CharField(max_length=512)

class Assignment(models.Model):
    someperson = models.ForeignKey(SomeOtherModel)

import weakref
_save_magic = weakref.WeakKeyDictionary()

@connect(pre_save, Assignment)
def Assignment_presave(sender, instance, **kwargs):
    if instance.pk:
        _save_magic[instance] = Assignment.objects.get(pk=instance.pk).someperson

@connect(post_save, Assignment)
def Assignment_postsave(sender, instance, **kwargs):
    old = None
    if instance in _save_magic:
        old = _save_magic[instance]
        del _save_magic[instance]
        LogModel(message="%s is no longer assigned to %s"%(old, self).save()
    LogModel(message="%s is now assigned to %s"%(instance.someperson, self).save()

Что думает StackOverflow? Что-нибудь лучше? Любые советы?

0 голосов
/ 16 апреля 2010

Это легко сделать с помощью сигналов . Для каждой модели Django имеется сигнал до сохранения и после сохранения .

...