Django:仅使用 annotate() 和 values() 计算非空 CharField
Posted
技术标签:
【中文标题】Django:仅使用 annotate() 和 values() 计算非空 CharField【英文标题】:Django : Count only non-empty CharField with annotate() & values() 【发布时间】:2014-07-14 05:28:43 【问题描述】:Django recommends 没有在 null
上使用 CharField
,但是 annotate 在计数中包含空字符串。有没有办法在不从查询中排除具有空字符串的行的情况下避免这种情况?
我的问题不仅仅是如何实现我的查询,而是从根本上说,注释/聚合计数是否应该包含空字段。 Django 认为空作为基于字符串的字段的 NULL 的替代品。
我的模特:
class Book(models.Model):
name = models.CharField(...)
class Review(models.Model):
book = models.ForeignKey()
category = models.ForeignKey()
review = models.CharField(max_length=200, default='', blank=True)
要按类别计算非空评论和分组,我使用
Review.objects.values('category').annotate(count=Count('review'))
这不起作用,因为 annotate 也计算空值(如果条目为 NULL,则不会这样做)。我可以在 annotate 调用之前过滤掉空字符串,但我的查询更复杂,我需要所有空和非空对象。
有没有更聪明的方法来使用 注释和跳过 count 中的空值,或者我应该从
更改模型review = models.CharField(max_length=200, default='', blank=True)
到
review = models.CharField(max_length=200, default=None, blank=True, null=True)
【问题讨论】:
Book.objects.filter(review != '').values('category').annotate(count=Count('review'))
来自问题描述:I could filter out empty strings before the annotate call but my Query is more complex and I need all empty & non-empty objects
恐怕添加null=True
对您没有帮助。您应该使用原始 sql 查询 docs.djangoproject.com/en/dev/topics/db/sql
可以用order_by方法,后跟distinct吗?但是,检查 django 文档,他们警告这种情况:docs.djangoproject.com/en/dev/ref/models/querysets/#distinct
【参考方案1】:
我遇到了非常相似的情况。我用Conditional Expressions解决了它:
review_count = Case(
When(review='', then=0),
default=1,
output_field=IntegerField(),
)
Review.objects.values('category').annotate(count=review_count)
【讨论】:
【参考方案2】:...我需要所有空的和非空的对象。
这在使用values
时没有任何意义。您将获得仅包含 category
和 count
键的字典列表,而不是实际对象。除了 count
中的不同数字之外,您会发现过滤出空的 review
值之间没有区别。最重要的是,您过滤一本书 (id=2
) 并以某种方式期望可以有多个评论。
您需要认真重新考虑您到底想要做什么,以及您的模型定义如何适应它。
【讨论】:
该查询将对模型的其他字段进行其他计算(平均值/最大值/最小值)。这些字段独立于review
。我想在一个查询中实现这一点。我编写了一个简化模型来专注于我所问的问题。为模型添加了更多细节以回答您的一些问题。以上是关于Django:仅使用 annotate() 和 values() 计算非空 CharField的主要内容,如果未能解决你的问题,请参考以下文章
Django基础aggregate和annotate方法使用详解与示例
django数据查询优化annotate和aggregate
使用 annotate() 包含一个 django 模型对象属性