2009-10-28 47 views
10

我试图在保存后立即更新记录。这个例子看似毫无意义,但想象一下,我们需要使用一个API的数据被保存到获得一些额外的信息和更新的记录后:django中的post_save立即更新实例

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) 

所以“额外”字段应该设置为“你好”每次保存后。正确?但它不起作用。

任何想法?

+0

也许你可以描述它是如何工作的?乍一看,它似乎会造成一个无限循环,因为post_save调用保存,它应该调用post_save等。也许Django阻止递归? – 2009-10-28 23:21:36

+0

我在那里看到一个无限循环。在t.save()发送post_save信号之后,猜猜哪个函数被调用... – stefanw 2009-10-28 23:22:04

+0

哦,我印象中Django不会让第二个保存触发post_save呢?我猜不会。在这种情况下,你是对的。这将是一个无限循环。但我没有看到循环或任何东西。 – givp 2009-10-28 23:28:53

回答

18

当您发现自己使用post_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) 
+1

如果他正在对管理模型执行此操作,则post_save是比继承现有管理模型和覆盖保存更好的解决方案。 – 2009-10-29 00:46:28

+0

@保罗麦克米兰为什么? – 2011-03-25 16:32:39

+0

在Django 1.3和更高版本的'save'方法参数列表中需要'using = False' – eviltnan 2012-07-20 13:11:47

6

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()方法。

+0

我其实也试过,也无济于事。但是如果上面的人是正确的,我不能这样做,因为它会卡在post_save循环中。 – givp 2009-10-28 23:30:03

+0

尝试使用创建的标志。我认为这应该解决你的问题,因为创建的后续循环通过未设置。 – 2009-10-28 23:31:34

+1

你可能想看看这个问题的更多信息,何时使用信号以及何时重写保存:http://stackoverflow.com/questions/170337/django-signals-vs-overriding-save-method – 2009-10-28 23:34:13