如何使用pre_delete信号普遍防止删除?

时间:2020-01-05 18:51:33

标签: django django-signals

我在所有模型上都有一个公共字段is_active = models.BooleanField()

我想为删除功能创建通用替代,以便代替从数据库is_active = False中删除记录。

我了解做到这一点的最佳方法是发出pre_delete信号,而不是将delete()本身改写为delete() is not called in bulk operations

我尝试了以下实现:

@receiver(pre_delete)
def delete_obj(sender, instance, **kwargs):
    """Override delete() to set object to inactive."""

    return instance.is_active == False

但是,这仍然导致对象从数据库中删除。我认为这是因为delete()之后仍被调用pre_delete。我该如何纠正?

从文档中

请注意,使用QuerySet批量删除对象或级联删除操作时,不必调用对象的delete()方法。为了确保执行自定义的删除逻辑,可以使用pre_delete和/或post_delete信号。

1 个答案:

答案 0 :(得分:0)

您要替换原始方法的逻辑(在这种情况下,执行更新而不是删除)对其进行扩展。< / p>

信号扩展 主要方法逻辑,而不是替换。

pre_信号中-在操作之前运行一些其他逻辑(甚至可以修改对象)。在post_信号中-在主要动作之后运行一些附加逻辑。但是主要动作仍在运行-应该-在代码中已正确调用-不应替换信号。

就像模型上的扩展方法一样:您将在调用super().method()之前或之后添加一些逻辑-这就是信号的工作方式。

如果用另一种逻辑替换方法逻辑-覆盖方法super()时很可能不会被调用,因此不会执行任何原始操作。


因此,要用自定义逻辑替换delete(),您可以覆盖两个模型的delete()方法,并使用被覆盖的delete()方法为模型使用自定义QuerySet,这样在调用delete()时,模型实例或QuerySet-它将执行更新。


Link to surce code where QuerySet delete is performed

  • pre_delete信号已发送
  • delete_batch已执行
  • post_delete信号已发送