Использование аннотации Django (Count) с обнуляемым ForeignKey - PullRequest
4 голосов
/ 24 июня 2011

На примере моделей из https://docs.djangoproject.com/en/dev/topics/db/queries/

Я хочу сделать что-то вроде следующего:

q = Entry.objects.filter(...)
entries = q.all().order_by('pub_date')
blog_counts = q.values('blog__name').annotate(Count('blog'))

Это возвращает мне результат, подобный следующему:

[{'blog__count': 3, 'blog__name': u'Cheddar Talk'}, {'blog__count': 5, 'blog__name': u'Beatles Blog'}]

Если Entry.blog ForeignKey сделан "null = True, blank = True", и я создаю несколько записей Entry с нулевым значением для блога, я получаю что-то вроде этого:

[{'blog__count: 0, 'blog__name': None}, {'blog__count': 3, 'blog__name': u'Cheddar Talk'}, {'blog__count': 5, 'blog__name': u'Beatles Blog'}]

Я ожидал получить фактическое количество записей без связанного с ним блога, а не 0. Глядя на выполненный SQL, я вижу, что он выполняет COUNT (blog. id) вместо чего-то вроде COUNT (* 1015). *. blog_id), но изменение на .annotate (Count ('blog_id')) дает мне:

FieldError: Cannot resolve keyword 'blog_id' into field.

Что я могу сделать, чтобы получить точное количество записей без соответствующего блога?

Ответы [ 2 ]

4 голосов
/ 24 июня 2011
Entry.objects.filter(blog__isnull=True).count()

Это даст вам то, что вы хотите.В вашем текущем коде Count дает вам именно то, что вы просили, количество блогов, с которыми связана каждая запись.В случае с нулевыми блогами, очевидно, это ноль.

0 голосов
/ 18 июля 2019

Сгенерированный оператор SQL использует предложение count в форме Count(<field_name>), которое не считает нули. К сожалению (по крайней мере, MySQL и PostgreSQL) бэкэнды включают нулевые значения в вывод, даже если нули не учитываются! Что оставляет у пользователя ложное впечатление, что нулевых значений нет вообще.

Решение

Сгенерированный оператор SQL должен иметь форму Count(*) вместо Count(<field_name>). Это приведет к правильному подсчету нулей.

blog_counts = q.values('blog__name').annotate(Count('*'))

См. Билет:

https://code.djangoproject.com/ticket/15183

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...