You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:52:26