在Django中使用post_save立即更新实例

13 投票
2 回答
16610 浏览
提问于 2025-04-15 15:28

我想在保存记录后立即更新它。这个例子看起来可能没什么意义,但想象一下,我们需要在数据保存后使用一个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 个回答

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()。不过在这里其实不需要这么做。因为 created 参数可以防止循环,它只在第一次设置的时候起作用。

一般来说,除非你真的需要使用 post_save 信号,否则你应该重写对象的 save() 方法。

21

当你发现自己在使用 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)

撰写回答