修改Django的pre_save / post_save数据

时间:2010-12-26 20:04:52

标签: django django-signals

我很难从django掌握这个post_save / pre_save信号。

我的模型有一个名为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_savepost_save

嗯......我想在django的宇宙中,在保存它之前(甚至之后)改变一个条目的能力是很常见的。那么,我在这里做错了什么?信号是错误的方法还是我错过了其他的东西?

此外,一旦触发了pre_save / post_save函数,是否可以访问另一个模型的实例并更改其上的特定行条目?

由于

2 个答案:

答案 0 :(得分:7)

在保存之前,信号不是更新同一模型中的字段的正确方法。覆盖模型的保存方法,而不是使用此情况下的信号。

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

对于其他型号的更新,信号是一种很好的方法,因为您可以轻松地将模型分离。具体来说,您可以添加pre_ / post_save信号来触发操作,而无需修改已保存模型的代码(可能驻留在第三方的另一个应用程序中)。

答案 1 :(得分:3)

我同意Carles的说法,这可能属于save()。当必须使用信号执行此操作时,请确保save()周围的情况非常紧张。您的测试可以重新编写为:

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

通过这种方式进行测试,你不会进入无限递归。