【问题标题】:post_save in django to update instance immediatelydjango 中的 post_save 立即更新实例
【发布时间】:2010-12-11 01:50:02
【问题描述】:

我正在尝试在记录保存后立即更新它。这个例子可能看起来毫无意义,但假设我们需要在保存数据后使用 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)

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

有什么想法吗?

【问题讨论】:

  • 也许你可以描述它是如何不工作的?乍一看,它似乎会造成一个无限循环,因为 post_save 调用了 save,它应该调用 post_save 等。也许 Django 正在阻止递归?
  • 我在那里看到了一个无限循环。在 t.save() 之后发送一个 post_save 信号,猜猜哪个函数被调用...
  • 哦,我的印象是Django不会让第二次保存再次触发post_save?我猜不会。在这种情况下,你是对的。这将是一个无限循环。但我没有看到循环或任何东西。
  • 这可能是一个愚蠢的问题,但是,您不能先调用 API 再保存吗?
  • 你的意思是使用pre_save?我必须在模型级别执行此操作,因为我无法以任何方式为此项目修改 Django 管理员。

标签: python django django-models


【解决方案1】:

当您发现自己使用 post_save 信号来更新 sender 类的对象时,您很可能应该重写 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)

【讨论】:

  • 如果他对管理模型执行此操作,post_save 是比继承现有管理模型和覆盖保存更好的解决方案。
  • using=False 在 Django 1.3 及更高版本的“保存”方法参数列表中需要
  • 覆盖保存方法并不总是合适的,因为在调用保存之前我们没有主键。因此,如果您需要使用实例的 PK,唯一的选项似乎是 post_save
  • 在包含所有必要参数的同时覆盖 save 方法的面向未来的方法是:def save(self, *args, **kwargs):
【解决方案2】:

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

【讨论】:

  • 我实际上也尝试过,但无济于事。但如果上面的人是正确的,我无论如何也不能这样做,因为它只会卡在 post_save 循环中。
  • 尝试使用创建的标志。我认为这应该可以解决您的问题,因为 created 在后续循环中未设置。
  • 您可能想查看此问题以获取有关何时使用信号以及何时覆盖保存的更多信息:stackoverflow.com/questions/170337/…
  • 哇!我将创建的标志的测试真值设置错误了一点。它现在应该可以工作了......
  • 原始发布者没有提到他希望仅在创建新记录时调用处理程序。因此,如果在更新时也必须调用处理程序,则使用“created”标志并不能解决问题。 (我自己也在尝试寻找类似问题的解决方案。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-18
  • 2014-05-23
  • 2021-11-26
  • 2019-01-11
相关资源
最近更新 更多