基于this SO question about counting forgein keys,我遇到了问题。这是我的模特:
class Type(models.Model):
is_bulk = models.BooleanField()
class Component(models.Model):
parent = models.ForgeinKey(Type, related_name="components")
我想编写一个包含所有类型的查询集,但那些具有is_bulk = True并且没有组件的查询集除外。如果is_bulk = False,则应包括它。如果is_bulk = True并且您有1个以上的链接组件,那么您就被包括在内。如果没有,你被排除在外。
根据答案,我尝试了这个查询集:
Type.objects.annotate(num_components=Count('components')).exclude(is_bulk=True, num_components=0)
但它没有返回任何结果。
然而,这意味着应该有结果:
>>> [(x.is_bulk, x.num_components) for x in Type.objects.annotate(num_components=Count('components'))]
[(False, 0), (False, 0), (False, 0), (False, 0), (False, 0), (False, 0), (False, 0)]
所有Type对象的is_bulk = False,并且所有对象都有0个Component。从阅读the .exclude(…) documentation开始,它应该是NOT(is_bulk=True AND num_components=0)
,对于每个类型都应为True。对? (我是否在这里犯了一个误解,如果是,那么正确的查询集是什么)
如果没有,为什么这个查询集会返回[]
,什么时候它应该返回所有这些?这是Django 1.3中的一个错误吗?
答案 0 :(得分:1)
我已通过将查询集更改为:
来解决此问题types_qs.annotate(num_components=Count('components')).filter(Q(is_bulk=False) | (Q(is_bulk=True) & Q(num_components__gt=0)))
这有效,但我不明白为什么我原来的没有。好吧。
答案 1 :(得分:0)
我尝试了这个例子,我认为您需要的是在您的字段中声明related_name
:
class Component(models.Model):
parent = models.ForgeinKey(Type, related_name='components')
应该这样做
<强>更新强>
根据您的示例:
>>> [(x.is_bulk, x.num_components) for x in Type.objects.annotate(num_components=Count('components'))]
[(False, 0), (False, 0), (False, 0), (False, 0), (False, 0), (False, 0), (False, 0)]
我的:
>>> [(x.is_bulk, x.num_components) for x in Type.objects.annotate(num_components=Count('components'))]
[(False, 3), (False, 0), (False, 1), (False, 4), (True, 2), (True, 3), (True, 1), (True, 1), (False, 2), (True, 7), (True, 0), (False, 0)]
我假设您没有符合查询集要求的对象:
Type.objects.annotate(num_components=Count('components')).exclude(is_bulk=True, num_components=0)
您的结果:
[]
这是我的结果:
[<Type: Type object>, <Type: Type object>, <Type: Type object>, <Type: Type object>]