Django信号与重写保存方法

imj*_*uez 81 python django django-signals django-models

我在缠绕这个问题时遇到了麻烦.现在我有一些看起来像这样的模型:

 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()
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*nan 79

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

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

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

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


gue*_*tli 18

您询问:

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

我在django文档中发现了这个:

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

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

遗憾的是,在批量创建或更新对象时没有解决方法,因为没有调用save(),pre_save和post_save.

From:覆盖预定义的模型方法

  • 它还说:“不幸的是,批量创建或更新对象时没有解决方法,因为没有调用save(),pre_save和post_save。” -因此,我认为这不是这些方法之间的折衷。 (3认同)
  • 这适用于两种方法,所以答案是:“不,与覆盖`save`方法相比,使用信号没有任何好处”? (3认同)
  • Django管理列表视图使用批量删除...混淆,直到遇到这个花絮. (2认同)

val*_*lex 5

Django 文档中关于批量删除(对象.delete()方法QuerySet)的小补充:

\n\n
\n

请记住,只要有可能,这将纯粹在 SQL 中执行,因此在此过程中不一定会调用各个对象实例的 delete() 方法。如果您\xe2\x80\x99 在模型类上提供\n 自定义delete() 方法并希望确保\n 调用该方法,则\xe2\x80\x9c 手动\xe2\x80\x9d 删除实例该模型的\n(例如,通过迭代 QuerySet 并分别对每个对象调用 delete() ),而不是使用 QuerySet 的批量 delete() 方法。

\n
\n\n

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

\n\n

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

\n\n
\n

最后,认识到 update() 在 SQL 级别进行更新,因此不会在模型上调用任何 save() 方法,也不会发出 pre_save 或 post_save 信号(这是 \n 的结果) n 调用 Model.save())。如果您想要更新具有自定义 save() 方法的模型的一堆记录,请循环遍历它们并调用 save()

\n
\n\n

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

\n