按天分组统计数量的查询

一、关键说明
Trunc('create_time', 'day')
作用:把 datetime 类型的 create_time 截断为日期(天),时分秒置 0
第一个参数:原时间字段;第二个参数:截断维度 day/hour/month/year
执行顺序(Django ORM 分组逻辑)
annotate(date=Trunc(...)):新增一个虚拟字段 date(仅保留日期)
.values('date'):指定分组字段,等价于 GROUP BY date
再 .annotate(count=Count('id')):分组后聚合计算条数
最终返回的数据结构示例
python
运行
[
{"date": "2026-06-11 00:00:00", "count": 12},
{"date": "2026-06-12 00:00:00", "count": 8}
]
二、配套序列化器适配(必做)
因为查询结果只有 date、count 两个字段,序列化器要对应:
python
运行

serializers.py

from rest_framework import serializers

class StatisticsSerializer(serializers.Serializer):
date = serializers.DateTimeField()
count = serializers.IntegerField()
注意:这里要用 Serializer,不要用 ModelSerializer,因为这是聚合查询结果,不是原生模型字段

三、拓展优化(可选)

  1. 日期格式化(去掉时分秒)
    如果只想返回 YYYY-MM-DD 格式,搭配 ExpressionWrapper + DateField:
    python
    运行
    from django.db.models import ExpressionWrapper, DateField

queryset = Statistic.objects.annotate(
date=ExpressionWrapper(
Trunc('create_time', 'day'),
output_field=DateField()
)
).values('date').annotate(count=Count('id')).order_by('date')
2. 只重写 list 接口(推荐)
如果这个接口只做统计查询,不需要增删改,改用 ReadOnlyModelViewSet:
python
运行
class Statisticsviewset(viewsets.ReadOnlyModelViewSet):
queryset = Statistic.objects.annotate(
date=Trunc('create_time', 'day')
).values('date').annotate(count=Count('id')).order_by('date')
serializer_class = StatisticsSerializer

四、 标准分组统计写法
需求:按 create_time 按天截断分组,统计每日数据条数

  1. 先补全依赖导入
    python
    运行
    from django.db.models import Count, Trunc
    from rest_framework import viewsets
    from .models import Statistic
    from .serializer import StatisticsSerializer

  2. 正确 QuerySet 写法(按天分组统计)
    python
    运行
    class Statisticsviewset(viewsets.ModelViewSet):
    queryset = Statistic.objects.annotate(
    # 按天截断时间字段
    date=Trunc('create_time', 'day')
    ).values('date') # 按 date 分组
    .annotate(count=Count('id')) # 分组后统计数量
    .order_by('date') # 可选:按日期排序

    serializer_class = StatisticsSerializer

posted @ 2026-06-11 18:01  ham0921  阅读(10)  评论(0)    收藏  举报