如何在Django中使用模型继承处理M2M关系的保存后信号?

如何在Django中使用模型继承处理M2M关系的保存后信号?,django,django-models,many-to-many,django-signals,Django,Django Models,Many To Many,Django Signals,问题的标题与句子完全相同,但希望下面的代码能够澄清这一点: class Foo(models.Model): ... class AbstractParent(models.Model): foos = models.ManyToManyField( Foo, related_name='%(app_label)s_%(class)s_related' ) def bar(self): ... cla

问题的标题与句子完全相同,但希望下面的代码能够澄清这一点:

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”

基本上,
ChildOne
ChildTwo
的基类对类
Foo
有一个M2M。我想做的是:每当保存
Foo
类的对象时,我想调用
ClassOne
ClassTwo
的所有对象的
bar()
方法,该方法通过
foos
字段与
Foo
对象相关。为此,我试着写一个简单的信号:

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
类的所有子类并调用它们的
bar()
方法?理想情况下,我只想查询我的数据库一次,在一次查询中,我想获得信号中与
实例相关的
ChildOne
ChildTwo
的所有对象。请注意,在我的实际模型中,
AbstractParent
有两个以上的子类,所以请给出一个记住这一点的答案。谢谢您的帮助。

好吧,它不能满足您的单一查询要求,但这里有一种方法至少可以通过查询每个子类来完成这项工作:

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对象的唯一方法是通过
select\u related
,这不适用于
manytomy
关系


如果单个查询很重要,那么实现可能需要有关
.bar()
的更具体的详细信息,这可能需要重构为一个类方法,该类方法可以处理
.values()
调用或其他调用的结果。

有没有办法在一个db查询中执行此查询?更新了更多详细信息,但简短的回答是:我还不够清楚。这是一个复杂的问题,这是我所知道的最好的实现。非常感谢。很抱歉再次提出此问题,但在测试代码后,我得到以下错误:TypeError:“ManyRelatedManager”对象不可编辑,在getattr(实例,字段.related\u名称)中的相关对象的
行中:
抱歉,我取消了
.all()
以使查询集可编辑。现在修好了。