Django QuerySet с исключением и аннотацией не возвращает никаких результатов

Основываясь на этот вопрос SO о подсчете forgein ключи, у меня проблема. Это мои модели:

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)]

Все объекты типа имеют is_bulk=False и все они имеют 0 компонентов. Прочитав документацию .exclude(…), должно быть NOT(is_bulk=True AND num_components=0), что должно быть True для каждого типа. Верно? (Я сделал здесь недоразумение, если да, то какой правильный набор запросов)

Если нет, то почему этот набор запросов возвращает [], когда он должен возвращать их все? Это ошибка в Django 1.3?


person Rory    schedule 10.11.2011    source источник
comment
Возможно, вы захотите распечатать атрибут запроса вашего Queryset, чтобы вы могли читать выходные данные SQL Django.   -  person Thomas Orozco    schedule 10.11.2011
comment
Вы можете попробовать исключить с одним параметром за раз, чтобы увидеть, в чем проблема: is_bulk=True, num_components=0 или в их совместном использовании.   -  person Lycha    schedule 10.11.2011
comment
В вашем models.py есть опечатка parent = models.ForgeinKey(Type) это должно быть ForeignKey   -  person César    schedule 10.11.2011


Ответы (2)


Я исправил это, изменив набор запросов на:

types_qs.annotate(num_components=Count('components')).filter(Q(is_bulk=False) | (Q(is_bulk=True) & Q(num_components__gt=0)))

Это работает, но я не понимаю, почему мой оригинальный не работал. Ах хорошо.

person Rory    schedule 14.11.2011

Я попробовал этот пример, и я думаю, что вам нужно объявить 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>]
person César    schedule 10.11.2011
comment
Я уже сделал это в своей модели, и проблема возникает. я обновил вопрос - person Rory; 10.11.2011