Django ORM按月份区间统计时When与Q对象报错如何解决?
Django ORM按月份区间统计记录数的报错修正方案
错误原因
- 第一次报错是因为直接在
When中使用Python原生的in关键字判断,该运算会直接在Python层返回布尔值,不是Django能识别的SQL查询表达式,不符合When的参数要求。 - 第二次报错是因为将Python运算得到的布尔值直接传入
Q()对象,Q()需要接收查询条件参数,无法解析布尔值,因此抛出解包错误。
修正后的代码
推荐使用Django ORM原生支持的日期字段查找语法,写法更简洁:
from django.db.models import Count, Case, When, IntegerField, F # 按年分组统计各季节的记录数 result_qs = Model.objects.values("created_on__year").annotate( spring=Count(Case( When(created_on__month__in=[1,2,3,4,5], then=1), output_field=IntegerField() )), summer=Count(Case( When(created_on__month__in=[6,7], then=1), output_field=IntegerField() )), fall=Count(Case( When(created_on__month__in=[8,9,10,11,12], then=1), output_field=IntegerField() )), year=F("created_on__year") )
如果需要显式使用ExtractMonth函数,写法如下:
from django.db.models import Count, Case, When, IntegerField from django.db.models.functions import ExtractYear, ExtractMonth result_qs = Model.objects.annotate( year=ExtractYear("created_on"), month=ExtractMonth("created_on") ).values("year").annotate( spring=Count(Case( When(month__in=[1,2,3,4,5], then=1), output_field=IntegerField() )), summer=Count(Case( When(month__in=[6,7], then=1), output_field=IntegerField() )), fall=Count(Case( When(month__in=[8,9,10,11,12], then=1), output_field=IntegerField() )) )
关键说明
- 要实现按年分组统计,必须在
annotate前调用values("year")指定分组字段,否则会返回每条记录的统计值,无法得到按年聚合的结果。 Case表达式建议显式指定output_field参数,避免Django自动推断字段类型出现异常。
内容的提问来源于stack exchange,提问作者hello
相关产品推荐
相关产品推荐

