如何通过Django ORM从Employee查询集按Business分组生成列表字典
Django ORM按Business分组员工(单查询实现)
先明确你的模型结构(示例):
from django.db import models class Business(models.Model): name = models.CharField(max_length=100) # 其他业务字段 class Employee(models.Model): name = models.CharField(max_length=100) business = models.ForeignKey(Business, on_delete=models.CASCADE, related_name='employees') # 其他员工字段
方案1:PostgreSQL环境下用聚合函数直接分组(推荐)
如果你的项目用PostgreSQL,可以利用Django提供的ArrayAgg或JSONBAgg聚合函数,直接在数据库层面完成分组,返回企业-员工列表的结构,全程单查询:
聚合员工字段(如姓名)
from django.contrib.postgres.aggregates import ArrayAgg from django.db.models import F # 查询每个企业及其对应的员工姓名列表 business_employee_map = Business.objects.annotate( employee_names=ArrayAgg(F('employees__name')) # 可替换为你需要的员工字段 ).values('name', 'employee_names') # 转成目标字典 result = {item['name']: item['employee_names'] for item in business_employee_map}
聚合完整员工对象
如果需要完整的员工对象数据,用JSONBAgg将员工字段序列化为JSON数组:
from django.contrib.postgres.aggregates import JSONBAgg from django.db.models.functions import JSONObject business_employee_map = Business.objects.annotate( employees_list=JSONBAgg( JSONObject( id=F('employees__id'), name=F('employees__name'), # 按需添加其他员工字段 ) ) ).values('name', 'employees_list') result = {item['name']: item['employees_list'] for item in business_employee_map}
方案2:从Employee查询集出发分组
如果你只能从Employee查询集入手(比如已经有employees = Employee.objects.select_related('business').all()),可以通过values+聚合函数实现分组:
from django.db.models import ArrayAgg # 按企业分组,聚合员工姓名 employee_groups = Employee.objects.values( 'business__name' # 按企业名称分组,也可用business__id保证唯一性 ).annotate( employee_names=ArrayAgg('name') ).order_by('business__name') result = {item['business__name']: item['employee_names'] for item in employee_groups}
方案3:适配MySQL等其他数据库
如果用MySQL,没有原生的ArrayAgg,可以自定义GROUP_CONCAT函数实现字符串聚合,之后再拆分:
from django.db.models import Func, F class GroupConcat(Func): function = 'GROUP_CONCAT' template = "%(function)s(%(expressions)s SEPARATOR ', ')" employee_groups = Employee.objects.values( 'business__name' ).annotate( employee_names=GroupConcat(F('name')) ).order_by('business__name') # 拆分字符串为列表 result = {item['business__name']: item['employee_names'].split(', ') for item in employee_groups}
以上所有方案均为单数据库查询,无需循环遍历每个Employee对象处理分组逻辑。
内容的提问来源于stack exchange,提问作者Amir Shabani
相关产品推荐
相关产品推荐

