Django post_save 在不覆盖模型 save() 的情况下防止递归

新手上路,请多包涵

有许多关于使用 post_save 信号递归的 Stack Overflow 帖子,绝大多数的评论和答案是:“为什么不覆盖 save()” 或仅在 created == True 触发的保存 ---

好吧,我相信有一个很好的案例不使用 save() 例如,我正在添加一个临时应用程序来处理与我们的订单模型完全分开的订单履行数据。

框架的其余部分完全不知道履行应用程序,并且使用 post_save 挂钩将所有与履行相关的代码与我们的订单模型隔离开来。

如果我们放弃 fulfillment 服务,我们的核心代码就不必改变。我们删除了履行应用程序,仅此而已。

那么,是否有任何合适的方法来确保 post_save 信号不会两次触发同一个处理程序?

原文由 Yuji ‘Tomita’ Tomita 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 421
2 个回答

您如何看待这个解决方案?

 @receiver(post_save, sender=Article)
def generate_thumbnails(sender, instance=None, created=False, **kwargs):

    if not instance:
        return

    if hasattr(instance, '_dirty'):
        return

    do_something()

    try:
        instance._dirty = True
        instance.save()
    finally:
        del instance._dirty

您还可以创建装饰器

def prevent_recursion(func):

    @wraps(func)
    def no_recursion(sender, instance=None, **kwargs):

        if not instance:
            return

        if hasattr(instance, '_dirty'):
            return

        func(sender, instance=instance, **kwargs)

        try:
            instance._dirty = True
            instance.save()
        finally:
            del instance._dirty

    return no_recursion

@receiver(post_save, sender=Article)
@prevent_recursion
def generate_thumbnails(sender, instance=None, created=False, **kwargs):

    do_something()

原文由 xakdog 发布,翻译遵循 CC BY-SA 3.0 许可协议

您可以在信号处理程序中使用更新而不是保存

queryset.filter(pk=instance.pk).update(....)

原文由 mossplix 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题