用外键集过滤器注释时结果错误

时间:2019-02-05 14:35:53

标签: python django django-models

模型C有到模型B的外键链接。模型B有到模型A的外键链接。也就是说,模型A实例可能有很多模型B实例,模型B可能有很多模型C实例。

伪代码:

class A:
    ...

class B:
    a = models.ForeignKey(A, ...)

class C:
    b = models.ForeignKey(B, ...)

我想从数据库中检索模型A的元素的整个列表,并用它具有的B元素的数量注释它,其中它们各自的C元素的数量不是零(或任何随机数) )。

我尝试过:

A.objects.annotate(
    at_least_one_count=Count('b', filter=Q(b__c__isnull=False))
)

据我所知,这应该是有效的。但是,返回的数字不正确(在实际情况下)。它返回的数字比没有过滤器的数字大,这显然是不可能的:

A.objects.annotate(
    at_least_one_count=Count('b')
)

编辑:当我为每个A实例分别运行以下查询时,我得到的数字是相同的,这使我认为我的代码中可能存在错误:

A.objects.first().b_set.filter(c__isnull=False).__len__()

注意:我想在不使用SQL的情况下执行此查询。如果我必须利用Django提供的一些更高级的Pythonic工具,只要我保持面向对象,我会很乐意这样做。我试图摆脱对所有数据库操作使用原始SQL的方式,并使用Django ORM将它们全部重写。但是,它似乎过于复杂。

1 个答案:

答案 0 :(得分:0)

答案很简单:应用转换为join语句的查询后,必须执行一个不同的on过滤器,这在Django中是通过对查询集调用.distinct(...)来完成的。 < / p>

在这种情况下,如果您使用过滤器,并且过滤器对象受到明显的限制,那么您要使用:

...=Count('b', filter=Q(b__c__isnull=False), distinct=True)
相关问题