Изменение данных Django pre_save / post_save - PullRequest
1 голос
/ 26 декабря 2010

Мне трудно понять сигналы post_save / pre_save от django.

Что происходит, так это то, что моя модель имеет поле с именем status, и когда запись в эту модель добавляется / сохраняется, ее статус должен быть изменен в соответствии с некоторым условием.

Моя модель выглядит так:

 class Ticket(models.Model):    
    (...)   
    status = models.CharField(max_length=1,choices=OFFERT_STATUS, default='O')

И мой обработчик сигнала, настроенный для pre_save:

def ticket_handler(sender, **kwargs):
   ticket = kwargs['instance']
   (...)
   if someOtherCondition:
       ticket.status = 'C'

Теперь, что произойдет, если я поставлю ticket.save() просто ниже этой последней строки if - это огромная итерационная черная дыра, поскольку это действие вызывает сам сигнал. И эта проблема возникает как в pre_save, так и в post_save.

Ну ... я думаю, что возможность изменить запись перед (или даже после) ее сохранением довольно распространена во вселенной django. Итак, что я здесь делаю не так? Сигналы - это неправильный подход, или я что-то здесь упускаю?

Кроме того, будет ли возможно, после запуска этой функции pre_save / post_save, получить доступ к экземпляру другой модели и изменить конкретную запись строки для этого?

Спасибо

Ответы [ 2 ]

7 голосов
/ 26 декабря 2010

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

def save(self, force_insert=False, force_update=False):
    status = whatever....
    super(Ticket, self).save(force_insert, force_update)

Для обновлений других моделей сигналы являются отличным подходом, поскольку вы можете легко разъединить ваши модели.В частности, вы можете добавить сигнал pre_ / post_save для запуска действий без необходимости изменять код сохраненной модели (который может находиться в другом приложении от третьей стороны).

3 голосов
/ 27 декабря 2010

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

   if someOtherCondition and ticket.status != 'C':
       ticket.status = 'C'
       ticket.save()

Вы не попадете в бесконечную рекурсию с тестом, выполненным таким образом.

...