一尘不染

Django post_save防止递归而不覆盖模型save()

django

有很多关于使用post_save信号进行递归的Stack Overflow帖子,其中的注释和答案绝大多数是“为什么不重写save()”或仅在其上触发的保存created == True

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

框架的其余部分非常高兴地没有意识到实现应用程序,并且使用post_save挂钩将所有与实现相关的代码与我们的Order模型隔离开来。

如果我们放弃履行服务,则无需更改核心代码。我们删除履行应用程序,仅此而已。

因此,是否有任何体面的方法来确保post_save信号不会两次触发同一处理程序?


阅读 419

收藏
2020-03-29

共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()
2020-03-29
一尘不染

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

queryset.filter(pk = instance.pk).update(....)
2020-03-29