Django QuerySet with exclude&注释不返回任何结果

时间:2011-11-10 14:32:42

标签: python django django-queryset django-orm

基于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中的一个错误吗?

2 个答案:

答案 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>]