Django中按日期及用户类型(管理员/客户)分组Ticket数据
Django Ticket数据分组实现方案
嘿,我来帮你搞定这个按日期+用户类型分组的需求!下面给你两种可行的实现方式,你可以根据数据量和场景来选:
方法一:Python层面分组(直观易理解,适合小数据量)
这种方式先把数据从数据库取出来,再用Python的itertools.groupby做分组,逻辑清晰,容易调试。
首先,我们先优化查询,避免N+1问题(提前关联User表),同时把日期截断到天:
from django.utils import timezone from django.db.models.functions import TruncDate from itertools import groupby # 获取所有Ticket并关联用户,同时提取预订日期的天部分 tickets = Ticket.objects.select_related('user').annotate( booked_day=TruncDate('booked_at') ).order_by('booked_day') # 分组前必须先排序,groupby依赖有序的迭代器
然后遍历分组,拆分管理员和客户的Ticket ID:
result = [] for booked_day, ticket_group in groupby(tickets, key=lambda t: t.booked_day): admin_ids = [] customer_ids = [] for ticket in ticket_group: # 这里假设User模型用is_staff标记管理员,如果你用的是is_superuser或者自定义字段,替换即可 if ticket.user.is_staff: admin_ids.append(ticket.id) else: customer_ids.append(ticket.id) result.append({ 'day': booked_day, 'booked_by_admin': admin_ids, 'booked_by_customer': customer_ids })
方法二:数据库层面分组(高效,适合大数据量)
如果你的Ticket数据量很大,推荐用数据库的聚合函数直接完成分组,减少Python内存占用和数据传输量:
from django.db.models import ArrayAgg, Case, When, Value from django.db.models.functions import TruncDate import django.db.models as models # 直接在数据库层面完成分组和聚合 queryset = Ticket.objects.select_related('user').annotate( booked_day=TruncDate('booked_at'), # 标记当前Ticket的用户是否为管理员 is_admin=Case( When(user__is_staff=True, then=True), default=False, output_field=models.BooleanField() ) ).values('booked_day').annotate( # 聚合管理员的Ticket ID列表 booked_by_admin=ArrayAgg( 'id', filter=models.Q(is_admin=True), default=Value([]) # 如果当天没有管理员预订,返回空列表 ), # 聚合客户的Ticket ID列表 booked_by_customer=ArrayAgg( 'id', filter=models.Q(is_admin=False), default=Value([]) ) ).order_by('booked_day') # 转换成你需要的列表格式 final_result = list(queryset)
注意事项
- 替换管理员判断字段:如果你的User模型不是用
is_staff标记管理员,记得把代码里的user__is_staff换成你的实际字段(比如user__is_superuser或者user__is_admin)。 - 日期截断逻辑:
TruncDate会把booked_at的datetime类型截断到日期部分(比如2018-05-06 14:30:00变成2018-05-06),确保同一天的Ticket会被分到一组。 - 空列表处理:方法二中的
default=Value([])保证了如果某天没有管理员或客户预订,对应的字段会返回空列表而不是None,更符合你的需求格式。
内容的提问来源于stack exchange,提问作者Aamu
相关产品推荐
相关产品推荐

