按天分组统计数量的查询
一、关键说明
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,因为这是聚合查询结果,不是原生模型字段
三、拓展优化(可选)
- 日期格式化(去掉时分秒)
如果只想返回 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 按天截断分组,统计每日数据条数
-
先补全依赖导入
python
运行
from django.db.models import Count, Trunc
from rest_framework import viewsets
from .models import Statistic
from .serializer import StatisticsSerializer -
正确 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
浙公网安备 33010602011771号