post_save в django для немедленного обновления экземпляра - PullRequest
10 голосов
/ 29 октября 2009

Я пытаюсь немедленно обновить запись после ее сохранения. Этот пример может показаться бессмысленным, но представьте, что нам нужно использовать API после сохранения данных, чтобы получить дополнительную информацию и обновить запись:

def my_handler(sender, instance=False, **kwargs):
    t = Test.objects.filter(id=instance.id)
    t.blah = 'hello'
    t.save()

class Test(models.Model):
    title = models.CharField('title', max_length=200)
    blah = models.CharField('blah', max_length=200)

post_save.connect(my_handler, sender=Test)

Таким образом, поле «extra» должно быть установлено в «hello» после каждого сохранения. Правильный? Но это не работает.

Есть идеи?

Ответы [ 2 ]

19 голосов
/ 29 октября 2009

Когда вы обнаружите, что используете сигнал post_save для обновления объекта класса отправителя, скорее всего, вам следует переопределить метод save. В вашем случае определение модели будет выглядеть так:

class Test(models.Model):
    title = models.CharField('title', max_length=200)
    blah = models.CharField('blah', max_length=200)

    def save(self, force_insert=False, force_update=False):
        if not self.blah:
            self.blah = 'hello'
        super(Test, self).save(force_insert, force_update)
6 голосов
/ 29 октября 2009

Не обрабатывает ли обработчик post_save экземпляр? Почему вы используете его для фильтрации? Почему бы просто не сделать:

def my_handler(sender, instance=False, created, **kwargs):
  if created:
     instance.blah = 'hello'
     instance.save()

Ваш существующий код не работает, потому что он зацикливается, и Test.objects.filter(id=instance.id) возвращает набор запросов, а не объект. Чтобы получить один объект напрямую, используйте Queryset.get(). Но вам не нужно делать это здесь. Созданный аргумент удерживает его от зацикливания, так как он устанавливает его только в первый раз.

В общем, если вам абсолютно не нужно использовать сигналы post_save, вы все равно должны переопределять метод save () вашего объекта.

...