关于Django ORM中Group By与Order By关联及Values返回对象的问题
Django ORM 问题解答
1. 为什么Order By中的字段会被自动纳入Group By条件?
这是因为主流数据库的SQL语法规范有强制要求:当使用GROUP BY做分组聚合时,ORDER BY里用到的非聚合字段必须出现在GROUP BY子句中(比如PostgreSQL、MySQL开启严格模式后都会检查这条规则)。
你的查询里,order_by指定了event__slug,但values只选了event(对应数据库的event_id),event__slug是关联表Event的字段,不属于你一开始指定的分组字段。Django ORM为了避免生成的SQL在数据库里报错,会自动把ORDER BY里的这类字段补到GROUP BY里,所以最终的GROUP BY就包含了event_id、cat_type和event.slug。
2. 使用Values('event')仅返回event_id而非Event对象,如何获取完整的Event对象?
values()本身就是用来返回字典格式的字段值的,不会返回模型实例,所以只会给你event对应的外键ID,拿不到完整的Event对象。要获取完整实例,有两种常用方式:
直接关联模型,不用values():
用select_related('event')提前关联Event表,再配合annotate和order_by:query_set = query_set.select_related('event').annotate(cat_count=Count('id')).order_by("event__slug", "cat_type")遍历这个
query_set时,每个对象都能通过obj.event直接访问完整的Event实例,同时obj.cat_count就是聚合后的统计值。如果需要分组统计+完整对象:
先通过ORM完成聚合和关联,再用Python的itertools.groupby做分组:from itertools import groupby # 先按排序条件查好数据,关联Event表 query_set = query_set.select_related('event').annotate(cat_count=Count('id')).order_by("event__slug", "cat_type") # 按event和cat_type分组 grouped_data = groupby(query_set, key=lambda item: (item.event, item.cat_type)) # 遍历分组结果 for (event_obj, cat_type), group_items in grouped_data: # event_obj就是完整的Event对象,cat_count可以取组内任意item的cat_count(聚合后每组值相同) count = next(group_items).cat_count
内容的提问来源于stack exchange,提问作者ARUNIMA DAS
相关产品推荐
相关产品推荐

