如何按预订日期分组Django的Ticket模型并获取每日工单ID列表
获取按日期分组的Django工单ID列表
嗨,我来帮你搞定这个需求!你已经实现了按日期统计工单总数,现在要改成获取每日的工单ID列表,这里有两种实用方案,我给你详细拆解:
方案一:数据库层面聚合(推荐,效率更高)
直接利用Django的数据库函数在数据库端完成分组和聚合,适合数据量较大的场景,性能表现更好。需要用到TruncDate(截断日期字段到天)和ArrayAgg(聚合ID为数组),注意ArrayAgg是PostgreSQL专属函数,如果你用其他数据库可能需要调整:
from django.db.models import ArrayAgg from django.db.models.functions import TruncDate # 按日期分组,聚合每个日期对应的工单ID列表 ticket_groups = Ticket.objects.annotate( # 将booked_at的时分秒截断,只保留日期部分 day=TruncDate('booked_at') ).values('day').annotate( # 把当前日期下所有工单的ID聚合为列表 ticket_list=ArrayAgg('id') ).order_by('day') # 转换成你需要的列表格式 result = list(ticket_groups)
执行后result的格式就和你预期的完全一致了:每个元素包含day(带日期的datetime对象)和ticket_list(对应日期的工单ID数组)。
方案二:Python层面分组(灵活度更高)
如果你的业务需要直接操作工单对象,或者用的是不支持ArrayAgg的数据库,可以先查询所有工单,再用Python的itertools.groupby做分组:
from itertools import groupby from django.utils import timezone # 必须先按预订日期排序,groupby只能对连续相同的键分组 tickets = Ticket.objects.order_by('booked_at') result = [] # 按预订日期的“日期部分”作为分组键 for day_date, ticket_group in groupby(tickets, key=lambda t: t.booked_at.date()): # 收集当前日期下所有工单的ID ticket_ids = [ticket.id for ticket in ticket_group] # 把date对象转成带时区的datetime对象(和示例格式匹配) aware_day = timezone.make_aware(timezone.datetime(day_date.year, day_date.month, day_date.day)) result.append({ 'day': aware_day, 'ticket_list': ticket_ids })
两种方案对比
- 方案一:数据库直接处理,速度快,内存占用低,适合大数据量;但依赖特定数据库的聚合函数特性。
- 方案二:纯Python处理,更灵活,能直接获取工单对象进行后续操作;但数据量很大时,处理速度和内存占用会不如方案一。
如果需要返回工单对象列表而不是ID列表,只需要把方案二中的ticket_ids = [ticket.id ...]改成ticket_objects = list(ticket_group),再将ticket_list替换为ticket_objects就可以啦~
内容的提问来源于stack exchange,提问作者Aamu
相关产品推荐
相关产品推荐

