Django中如何从QuerySet快速获取加权平均值且不使用循环
Django ORM 无循环计算QuerySet加权平均值
完全可以不用循环实现,直接使用Django ORM的聚合能力在数据库层面完成计算,性能远高于Python层循环处理。
前置依赖导入
from django.db.models import Sum, F, ExpressionWrapper, DecimalField
完整实现代码
# 过滤出day=1的记录,直接在数据库侧完成聚合计算 aggregate_result = Product.objects.filter(day=1).aggregate( # 计算所有(价格*权重)的总和,指定输出类型保证精度 weighted_total = Sum( ExpressionWrapper(F('price') * F('weighted'), output_field=DecimalField(max_digits=15, decimal_places=2)) ), # 计算权重总和 weight_sum = Sum('weighted') ) # 处理除零边界情况,计算最终结果 if not aggregate_result['weight_sum'] or aggregate_result['weight_sum'] == 0: day_1_average_weighted = 0 else: day_1_average_weighted = round(aggregate_result['weighted_total'] / aggregate_result['weight_sum'], 2)
说明
- 所有计算逻辑都在数据库层面执行,不会把全量数据拉取到Python内存,数据量越大性能优势越明显
F表达式用于直接引用数据库字段做运算,避免数据读取开销ExpressionWrapper指定运算输出类型为Decimal,避免不同字段类型运算导致的精度丢失- 增加了除零判断,避免所有权重都为0时触发除以零的报错
- 最后用
round保留两位小数,即可得到你预期的71.88格式的结果
小提示:你的模型定义中day字段存在笔误,正确写法是models.IntegerField()。
内容的提问来源于stack exchange,提问作者Maddie Graham
相关产品推荐
相关产品推荐

