Django最佳实践:按模型ID汇总总金额的实现方案
最佳实现方案
针对你的需求,有两种主流实现方式,分别适用于不同场景:
1. 数据库层面聚合(推荐,效率优先)
如果你的reports是Django ORM的QuerySet,直接在数据库层面做分组求和是最优解——避免把大量数据加载到内存,减少计算开销。
示例代码:
from django.db.models import Sum # 按num分组,聚合total_amount的总和,同时保留title(若同一num对应多个title,需根据业务确定取法,这里默认取分组内第一个) aggregated_data = reports.values('num', 'title').annotate(total_sum=Sum('total_amount')) data = [] for item in aggregated_data: data.append(DataModel( model_id=item['num'], title=item['title'], total_price=item['total_sum'] ))
注意:如果同一
num对应不同title,需要调整聚合逻辑,比如使用First('title')确保取到固定值,或者业务上保证num与title一一对应。
2. Python内存中处理(适合无法数据库聚合的场景)
如果reports已经是内存中的对象列表,或无法通过数据库聚合处理,可以用字典分组或itertools.groupby实现:
方式一:用defaultdict分组(简单直观)
from collections import defaultdict sum_map = defaultdict(lambda: {'total': 0, 'title': ''}) for report in reports: key = report.num sum_map[key]['total'] += report.total_amount # 仅在首次遇到该key时设置title,避免被后续不同title覆盖 if not sum_map[key]['title']: sum_map[key]['title'] = report.title # 转换为DataModel列表 data = [ DataModel( model_id=model_id, title=info['title'], total_price=info['total'] ) for model_id, info in sum_map.items() ]
方式二:用itertools.groupby(需先排序)
from itertools import groupby # 先按num排序,确保同组元素连续(groupby要求同组元素相邻) sorted_reports = sorted(reports, key=lambda x: x.num) data = [] for num, report_group in groupby(sorted_reports, key=lambda x: x.num): total_price = 0 title = '' for report in report_group: total_price += report.total_amount if not title: title = report.title data.append(DataModel( model_id=num, title=title, total_price=total_price ))
内容的提问来源于stack exchange,提问作者Mehdi Aria
相关产品推荐
相关产品推荐

