使用Django annotate(Count)和可空的ForeignKey

时间:2011-06-24 19:15:20

标签: django

使用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”,并且我为blog创建了几个具有null值的Entry记录,我会得到这样的结果:

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

我希望获得没有Blog关联的条目的实际数量,而不是0.查看执行的SQL,我看到它正在执行COUNT(blogid)而不是像COUNT(entryblog_id),但更改为.annotate(Count('blog_id'))会给我:

FieldError: Cannot resolve keyword 'blog_id' into field.

如果没有关联的Blog,我该怎么做才能获得准确的条目数?

2 个答案:

答案 0 :(得分:4)

Entry.objects.filter(blog__isnull=True).count()

那会给你你想要的东西。在您当前的代码中,Count正在为您提供您所要求的内容,即每个条目与之关联的博客数量。对于具有空博客的那些,显然是零。

答案 1 :(得分:0)

生成的SQL语句使用Count(<field_name>)形式的count子句,该子句不计算空值。不幸的是(至少MySQL和PostgreSQL)后端在输出中包含空值,即使不计算空值也是如此!这给用户留下了错误的印象,那就是根本没有空值。

解决方案

生成的SQL语句的格式必须为Count(*),而不是Count(<field_name>)。这将导致正确的空计数。

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

查看票证:

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