Q:

Django QuerySet with exclude & annotate not returning any results

Based off this SO question about counting forgein keys, I have a problem. This is my models:
class Type(models.Model):
  is_bulk = models.BooleanField()

class Component(models.Model):
  parent = models.ForgeinKey(Type, related_name="components")

I want to write a queryset that has all types, except those that have is_bulk=True and have no components. If is_bulk=False, it should be included. If is_bulk=True and you have 1+ linked Components, then you're included. If not, you're excluded.
Based off the answer, I tried this queryset:
Type.objects.annotate(num_components=Count('components')).exclude(is_bulk=True, num_components=0)

But it returns no results.
However this implies that there should be results:
>>> [(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)]

All the Type objects have is_bulk=False and all of them have 0 Components. From reading the .exclude(…) documentation, it should be NOT(is_bulk=True AND num_components=0), which should be True for every Type. Right? (Have I made a misunderstanding here, if so, what's the correct queryset)
If not, why is this queryset returning [], when it should return all of them? Is this a bug in Django 1.3?

A:

I have fixed this by changing the queryset to:
types_qs.annotate(num_components=Count('components')).filter(Q(is_bulk=False) | (Q(is_bulk=True) & Q(num_components__gt=0)))

That works, but I can't see why my original one didn't. Ah well.

