Django信号与重写保存方法

时间:2008-10-04 13:37:12

标签: python django django-models django-signals

我无法绕过这个问题。现在我有一些看起来像这样的模型:

 def Review(models.Model)
    ...fields...
    overall_score = models.FloatField(blank=True)

def Score(models.Model)
    review = models.ForeignKey(Review)
    question = models.TextField()
    grade = models.IntegerField()

评论有几个“分数”,overall_score是分数的平均值。保存评论或分数时,我需要重新计算total_score平均值。现在我正在使用重写的保存方法。使用Django的信号调度员会有什么好处吗?

6 个答案:

答案 0 :(得分:77)

保存/删除信号通常在您需要进行不完全特定于相关模型的更改的情况下有用,或者可以应用于具有某些共同点的模型,或者可以配置为跨模型使用的模型

重写save方法的一个常见任务是从模型中的某些文本字段自动生成slug。这是一个例子,如果你需要为许多模型实现它,将会受益于使用pre_save信号,其中信号处理程序可以将slug字段的名称和字段的名称改为从中产生slu ..一旦你有这样的东西,你实施的任何增强功能也将适用于所有模型 - 例如查找要为相关模型类型添加的slug,以确保唯一性。

可重复使用的应用程序通常受益于信号的使用 - 如果它们提供的功能可以应用于任何模型,它们通常(除非它是不可避免的)不希望用户必须直接修改他们的模型才能从中受益

例如,使用django-mptt,我使用pre_save信号来管理一组字段,这些字段描述了即将创建或更新的模型的树结构以及{{1} } signal用于删除被删除对象的树结构细节及其之前的对象的整个子树,并删除它们。由于信号的使用,用户不必在他们的模型上添加或修改pre_deletesave方法来为他们完成此管理,他们只需要让django-mptt知道哪些模型他们希望它能够管理。

答案 1 :(得分:17)

你问:

使用Django的信号调度程序会有什么好处吗?

我在django docs中找到了这个:

  

批量操作不会调用重写的模型方法

     

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

     

不幸的是,创建或更新时没有解决方法   批量对象,因为save(),pre_save和post_save都不是   调用。

来自:Overriding predefined model methods

答案 2 :(得分:3)

如果您使用信号,则每次保存相关分数模型时您都可以更新评分。但是,如果不需要这样的功能,我认为没有任何理由将其置于信号中,这与模型相关的东西非常相似。

答案 3 :(得分:2)

这是一种非规范化。看看这个pretty solution。就地组成字段定义。

答案 4 :(得分:1)

Django文档中有关批量删除的小添加(.delete()个对象上的QuerySet方法):

  

请记住,这将尽可能地在   SQL,因此单个对象实例的delete()方法将   不一定在过程中被调用。如果您提供了   在模型类上自定义delete()方法,并希望确保它是   调用后,您将需要“手动”删除该模型的实例   (例如,通过遍历QuerySet并在每个QuerySet上调用delete()   单个对象),而不是使用a的批量delete()方法   QuerySet。

https://docs.djangoproject.com/en/1.11/topics/db/queries/#deleting-objects

批量更新(.update()个对象上的QuerySet方法):

  

最后,意识到update()在SQL级别进行更新,并且   因此,不会在模型上调用任何save()方法,也不会   发出pre_save或post_save信号(这是由于   调用Model.save())。如果您要更新一堆记录   具有自定义save()方法的模型,对其进行循环并调用save()

https://docs.djangoproject.com/en/2.1/ref/models/querysets/#update

答案 5 :(得分:-26)

当您必须执行某些长期流程并且不想阻止您的用户等待保存完成时,信号非常有用。