如何用Django ORM按另一属性唯一值分组获取模型属性列表?
Django ORM按属性分组获取另一属性值列表
问题描述
现有如下Django模型:
class Result(models.Model): color = models.CharField() score = models.IntegerField()
数据库中有四条数据:
results = [ Result(color="blue", score=5), Result(color="blue", score=3), Result(color="red", score=10), Result(color="red", score=8), ]
希望通过Django ORM获取按color唯一值分组后的score列表,期望结果格式如下:
[ {"color": "blue", "scores": [5, 3]}, {"color": "red", "scores": [10, 8]}, ]
已知可以通过以下代码按color分组计算平均分:
results.values("color").annotate(avg_score=Avg("score"))
想确认是否能通过Django的聚合/注解功能直接获取分组后的原始score列表。
解决方案
方法一:PostgreSQL专属方案(一步实现)
如果你的项目使用PostgreSQL数据库,可直接使用Django提供的ArrayAgg聚合函数完成需求:
from django.contrib.postgres.aggregates import ArrayAgg # 按color分组,聚合score为列表 grouped_result = Result.objects.values("color").annotate(scores=ArrayAgg("score")).order_by("color")
执行后得到的QuerySet结构完全符合预期:
<QuerySet [{'color': 'blue', 'scores': [5, 3]}, {'color': 'red', 'scores': [10, 8]}]>
方法二:通用兼容方案(支持所有数据库)
若使用MySQL、SQLite等其他数据库,或需要跨数据库兼容,可以先查询全量数据,再用Python手动分组:
from itertools import groupby from operator import attrgetter # 先按color排序,保证groupby能正确分组 sorted_results = Result.objects.order_by("color") grouped_data = [] # 遍历分组,整理成目标格式 for color, group in groupby(sorted_results, key=attrgetter("color")): grouped_data.append({ "color": color, "scores": [item.score for item in group] })
最终grouped_data即为所需结果。
补充说明
ArrayAgg是PostgreSQL独有的聚合函数,依赖PostgreSQL数组类型,其他数据库无法使用。- 使用
values()+annotate()时,values()指定的字段会作为分组键,聚合函数会针对每个分组计算结果。
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

