Django信号与重写保存方法
-
05-07-2019 - |
题
我无法绕过这个问题。现在我有一些看起来像这样的模型:
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()
评论有几个“得分”,整体评分是得分的平均值。保存评论或分数时,我需要重新计算total_score平均值。现在我正在使用重写的保存方法。使用Django的信号调度员会有什么好处吗?
解决方案
保存/删除信号通常在您需要进行不完全特定于相关模型的更改的情况下有用,或者可以应用于具有某些共同点的模型,或者可以配置为跨模型使用的模型
重写 save
方法的一个常见任务是从模型中的某些文本字段自动生成slug。这是一个例子,如果你需要为许多模型实现它,将受益于使用 pre_save
信号,其中信号处理程序可以采用slug字段的名称和名称该领域产生的slu ..一旦你有这样的东西,你实施的任何增强功能也将适用于所有模型 - 例如查找要为相关模型类型添加的slug,以确保唯一性。
可重复使用的应用程序通常受益于信号的使用 - 如果它们提供的功能可以应用于任何模型,它们通常(除非它是不可避免的)不希望用户必须直接修改他们的模型才能从中受益
例如,使用 django-mptt ,我使用 pre_save
用于管理一组字段,用于描述即将创建或更新的模型的树结构,以及 pre_delete
信号,用于删除要删除的对象的树结构详细信息及其它之前的整个子树对象都被删除了。由于信号的使用,用户不必在他们的模型上添加或修改 save
或 delete
方法来为他们完成此管理,他们只需要让django-mptt知道他们想要管理哪些模型。
其他提示
你问:
使用Django的信号调度程序会有什么好处吗?
我在django docs中找到了这个:
批量操作不会调用重写的模型方法
请注意,不一定要调用对象的delete()方法 使用QuerySet或作为a的结果批量删除对象时 级联删除。为了确保执行自定义删除逻辑,您 可以使用pre_delete和/或post_delete信号。
不幸的是,创建或更新时没有解决方法 批量对象,因为save(),pre_save和post_save都不是 调用。
发件人:覆盖预定义的模型方法
如果您使用信号,则每次保存相关分数模型时您都可以更新评分。但如果不需要这样的功能,我认为没有任何理由将其置于信号中,这是与模型相关的相当的东西。
这是一种非规范化。请查看此漂亮的解决方案。就地组成字段定义。
Django文档中关于 QuerySet
对象的批量删除( .delete()
方法)的小补充:
请记住,只要有可能,这将纯粹执行 SQL,以及各个对象实例的delete()方法 在此过程中不一定要被调用。如果你提供了一个 模型类上的自定义delete()方法,并希望确保它是 叫,你需要手动”删除该模型的实例 (例如,通过遍历QuerySet并在每个上调用delete() 单独的对象)而不是使用的批量delete()方法 查询集。
https://docs.djangoproject.com/烯/ 1.11 /主题/分贝/查询/#删除的对象
QuerySet
对象上的批量更新( .update()
方法):
的更新最后,意识到update()在SQL级别进行更新, 因此,不会在模型上调用任何save()方法,也不会 发出pre_save或post_save信号(这是...的结果 调用Model.save())。如果你想更新一堆记录 具有自定义save()方法的模型,循环遍历它们并调用save()
当您必须执行某些长期流程并且不想阻止您的用户等待保存完成时,信号非常有用。