如何用Django ORM按日/月/小时统计DateTimeField条目数?
Django ORM按时间维度统计条目数量的最优方法
假设你的模型为MyModel,其中包含DateTimeField类型的timestamp字段,以下是仅用Django ORM按不同时间维度统计条目数量的最优方案:
按日统计
使用TruncDate函数将timestamp截断到日期维度,再分组统计:
from django.db.models import Count from django.db.models.functions import TruncDate daily_counts = MyModel.objects.annotate( date=TruncDate('timestamp') ).values('date').annotate( count=Count('id') ).order_by('date')
返回结果为有序查询集,每条数据包含date(日期对象)和count(当日条目数),格式示例:[{'date': datetime.date(2024, 5, 1), 'count': 15}, ...]
按月统计
使用TruncMonth函数截断到月份维度(返回当月第一天的datetime对象):
from django.db.models import Count from django.db.models.functions import TruncMonth monthly_counts = MyModel.objects.annotate( month=TruncMonth('timestamp') ).values('month').annotate( count=Count('id') ).order_by('month')
结果示例:[{'month': datetime.datetime(2024, 5, 1, 0, 0), 'count': 42}, ...]
按小时统计
使用TruncHour函数截断到小时维度(返回对应小时起始的datetime对象):
from django.db.models import Count from django.db.models.functions import TruncHour hourly_counts = MyModel.objects.annotate( hour=TruncHour('timestamp') ).values('hour').annotate( count=Count('id') ).order_by('hour')
结果示例:[{'hour': datetime.datetime(2024, 5, 1, 10, 0), 'count': 8}, ...]
额外说明
- 上述
Trunc系列函数是Django 1.10及以上版本内置的ORM函数,完全无需编写原生SQL,数据库层面直接完成截断和分组计算,性能最优。 - 可通过
filter方法添加时间范围过滤,例如filter(timestamp__gte=datetime(2024,1,1), timestamp__lte=datetime(2024,5,31)),缩小统计范围提升效率。 - 若需要自定义时间格式(如将月份转为
"2024-05"字符串),可在Python层面处理查询集结果,或结合Extract系列函数在ORM中完成字段转换。
内容的提问来源于stack exchange,提问作者Dmitry Sazhnev
相关产品推荐
相关产品推荐

