如何在 Django 中处理具有模型继承的 M2M 关系的 post-save 信号?

How to handle a post-save signal for an M2M relationship with model inheritance in Django?

问题的标题很完整,但希望下面的代码能把它弄清楚:

class Foo(models.Model):
    ...


class AbstractParent(models.Model):
    foos = models.ManyToManyField(
        Foo,
        related_name='%(app_label)s_%(class)s_related'
    )

    def bar(self):
        ...

    class Meta:
        abstract = True


class ChildOne(AbstractParent):
    ...


class ChildTwo(AbstractParent):
    ...

假设我的应用程序标签是 'myapp'。

基本上,ChildOneChildTwo 的基数 class 有一个 M2M 到 class Foo。我想做的是:每当保存 Foo class 的 object 时,我想调用所有 object 的 bar() 方法ClassOneClassTwo 通过 foos 字段与 Foo object 相关。为此,我尝试编写一个简单的信号:

from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=Foo)
def call_bar_for_all_related_objects_to_foo(sender, instance, **kwargs):
    # Do the thing

在这一点上,我有点迷路了。如何查询 AbstractParent class 的所有 children classes 并在与 [=24= 有关系时调用它们的 bar() 方法] 在信号?理想情况下,我只想查询我的数据库一次,并且在一次查询中,我想获取与 instance 中的 instance 相关的 ChildOneChildTwo 的所有 object信号。请注意,在我的实际模型中,AbstractParent 有两个以上的 child class,因此请记住这一点的答案表示赞赏。感谢您的帮助。

好吧,它不能满足您的单一查询要求,但这里有一种方法至少可以通过每个 child class:

的查询来完成工作
def call_bar_for_all_related_objects_to_foo(sender, instance, **kwargs):
    for field in instance._meta.get_fields():
        if not field.related_model:
            continue
        if not issubclass(field.related_model, AbstractParent):
            continue
        for related_object in getattr(instance, field.related_name).all():
            related_object.bar()

单个查询更新

我不认为这可以通过像这样的一般方式在单个查询中完成。我知道从单个查询中获取整个相关的 django objects 的唯一方法是通过 select_related,它不适用于 ManyToMany 关系。

如果单个查询很重要,实施可能需要关于 .bar() 的更具体细节,这可能需要重构为 class 方法,该方法适用于 .values()打电话什么的。