Django通过父对象获取子对象

fil*_*ilt 3 python django django-models

我试图通过父对象访问子对象,因为我想根据对象的类型执行不同的操作。我所拥有的是:

#models.py
class A(models.Model):
    ...

class B(A):
    field1 = models.CharField(...)
    ...

class C(A):
    field2 = models.IntegerField(...)
Run Code Online (Sandbox Code Playgroud)

我可以执行 2 个 for 循环并完成我想要的:

for obj in B.objects.all():
    if field1 == 'something':
        do some operation

for obj in C.objects.all():
    if field2 == 5:
        do some other operation
Run Code Online (Sandbox Code Playgroud)

但我在想,难道不能用 1 个 for 循环来做到这一点并通过父级访问子级吗?

for obj in A.objects.all():
    if obj.b and obj.b.field1 == 'something':
        do some operation
    elif obj.c and obj.c.field2 == 5:
        do some other operation
Run Code Online (Sandbox Code Playgroud)

我还认为select_lated可能可以解决问题,但它说它仅适用于ForeignKey.

此外,我希望在不使用django-model-utilsdjango-polymorphic等其他应用程序的情况下完成此操作,因为我觉得应该有一个简单的查询操作来完成此操作。

Ozg*_*ali 5

您可以像在最后的 for 循环中那样从父对象获取子对象,但您还需要检查父对象是否存在子对象,如下所示:

for obj in A.objects.all():
    try:
        if obj.b.field1 == 'something':
            do some operation
    except ObjectDoesNotExist:
        # obj does not have a child of class B

    try:
        if obj.c.field2 == 5:
            do some other operation
    except ObjectDoesNotExist:
        # obj does not have a child of class C
Run Code Online (Sandbox Code Playgroud)

您还可以使用 Q 对象将其组合到单个查询中:

A.objects.filter(Q(b__isnull=False, b__field1='something') | Q(c__isnull=False, c__field2=5))
Run Code Online (Sandbox Code Playgroud)

这将返回 A 类的对象