Django中如何在annotate()内为Count聚合函数添加筛选条件?
Django注解中为Count聚合添加筛选条件的正确实现
你尝试的三种写法无法生效的原因分别是:
- 写法1:
Count聚合不支持直接传入模型字段作为关键字参数,validated=True会被识别为非法参数抛出异常 - 写法2:Django聚合函数实例不支持链式调用
.filter()方法,运行时会直接报属性不存在错误 - 写法3:语法本身符合Django 2.0+的规范,但你漏了关联字段的双下划线前缀,ORM会默认去
Post主表查找validated字段,而非关联的user_comment表字段,因此筛选逻辑不生效
Django 2.0 及以上版本(推荐写法)
该版本开始聚合函数原生支持filter参数,传入Q对象即可完成筛选,注意关联字段必须用关联名__字段名的双下划线格式,完整代码:
from django.db.models import Count, Q all_posts = Post.objects.all().annotate( count_comments=Count('user_comment', filter=Q(user_comment__validated=True)) )
最终返回的每个Post实例的count_comments属性,就是该文章下已通过校验的评论总数。
Django 1.x 低版本兼容写法
低于2.0的Django版本没有聚合filter参数,可以通过Case When条件聚合实现相同效果:
from django.db.models import Count, Case, When, IntegerField all_posts = Post.objects.all().annotate( count_comments=Count( Case( When(user_comment__validated=True, then=1), output_field=IntegerField() ) ) )
踩坑提示:只要是在主表查询中筛选关联表的字段,都必须遵循
关联关系名__字段名的双下划线语法,否则ORM会将字段归属于当前主表,直接导致筛选逻辑不符合预期甚至报错。
内容的提问来源于stack exchange,提问作者RyanOh
相关产品推荐
相关产品推荐

