Django ORM使用aggregate统计试驾数量时过滤条件不生效问题排查
问题解决办法
根因分析
- 第一种可能:你使用的Django版本低于2.0,
Count聚合函数的filter参数是Django 2.0版本才新增的特性,低版本运行时会直接忽略该参数,导致两个统计项都是计算符合feature=feature_obj的总记录数,最终数值完全一致。 - 第二种可能:Django版本满足要求,但查询存在多表关联JOIN导致记录重复,进而出现统计值异常。
修复方案
方案1(适配Django 2.0+)
调整Count的统计字段为主键id,如果有重复记录可添加distinct=True参数:
from django.db.models import Count, Q obj = TestRide.objects.filter(feature=feature_obj).aggregate( scheduled_count=Count('id', filter=Q(status='Scheduled')), completed_count=Count('id', filter=Q(status='Completed')) ) # 存在多表关联导致重复记录时用下面的写法 # obj = TestRide.objects.filter(feature=feature_obj).aggregate( # scheduled_count=Count('id', filter=Q(status='Scheduled'), distinct=True), # completed_count=Count('id', filter=Q(status='Completed'), distinct=True) # )
你可以通过打印原生SQL验证过滤条件是否生效:
from django.db import connection # 执行完aggregate后打印最新的SQL print(connection.queries[-1]['sql'])
方案2(全Django版本兼容)
用Sum配合Case/When实现条件统计,完全规避filter参数的版本兼容问题:
from django.db.models import Sum, Case, When, IntegerField obj = TestRide.objects.filter(feature=feature_obj).aggregate( scheduled_count=Sum( Case(When(status='Scheduled', then=1), default=0, output_field=IntegerField()) ), completed_count=Sum( Case(When(status='Completed', then=1), default=0, output_field=IntegerField()) ) )
内容的提问来源于stack exchange,提问作者steve harvey
相关产品推荐
相关产品推荐

