Django中MySQL按DateTime字段日期分组聚合求和异常问题
Django按日期分组求和:SQLite正常但MySQL返回异常结果
模型定义
class Data(models.Model): created_at = models.DateTimeField(default=timezone.now) number = models.IntegerField(default=1)
需求
提取created_at字段的日期部分进行分组,计算每组number字段的总和。
测试代码
qs = Data.objects.values('created_at__date').annotate(sum=Sum('number'))
问题表现
上述查询在SQLite环境中运行正常,但在MySQL中执行后返回错误结果:
<QuerySet [{'created_at__date': None, 'sum': 100}]>
期望结果
<QuerySet [ {'created_at__date': datetime.date(2021, 7, 12), 'sum': 50}, {'created_at__date': datetime.date(2021, 7, 13), 'sum': 50} ]>
解决办法
方法1:使用TruncDate显式截断日期
Django的TruncDate函数能正确处理时区转换,确保MySQL可以识别分组字段:
from django.db.models.functions import TruncDate qs = Data.objects.annotate(created_date=TruncDate('created_at'))\ .values('created_date')\ .annotate(sum=Sum('number'))\ .order_by('created_date')
通过先将created_at截断为日期字段created_date,再以此字段分组求和,能避免MySQL对隐式日期转换的处理差异。
方法2:配置MySQL连接时区
如果Django启用了时区(USE_TZ = True),需确保MySQL连接的时区和Django配置一致。在settings.py的数据库配置中添加时区参数:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': '你的数据库名', 'USER': '用户名', 'PASSWORD': '密码', 'HOST': 'localhost', 'PORT': '3306', 'OPTIONS': { 'init_command': "SET sql_mode='STRICT_TRANS_TABLES', time_zone='+00:00'", }, } }
这里的time_zone值要和Django的TIME_ZONE设置匹配,比如Django用UTC就设为+00:00,如果用Asia/Shanghai,需确保MySQL已加载对应时区数据,可设置为'+08:00'或'Asia/Shanghai'。
内容的提问来源于stack exchange,提问作者Mas Zero
相关产品推荐
相关产品推荐

