预计阅读时间:3 分钟
django 设置时区支持导致 mysql 查询报错
背景:为什么要开 USE_TZ
在 django settings 中设置 USE_TZ = True 是官方推荐的做法,也是 django 5.0 之后的默认值。官方文档的说明:
当启用对时区的支持时,Django 在数据库中以 UTC 为单位存储日期时间信息,在内部使用具有时区的日期时间对象,并在模板和表单中将其转换为最终用户的时区。
如果用户居住在多个时区,这会很方便:你要根据用户的时间来显示日期信息。
即使你的网站只在一个时区提供服务,在数据库中用 UTC 存储数据仍然是一个好的做法,主要原因是夏令时(DST)。许多国家都有 DST 系统:春天时钟向前拨,秋天向后拨。如果你直接用当地时间工作,转换发生时就可能遇到一年两次的错误。这对博客也许无所谓,但如果是每年两次向客户多收或少收一小时的费用,就是真问题了。解决办法是在代码中使用 UTC,只在与终端用户交互时使用当地时间。
可以看到,开启时区支持后,时区转换的问题完全交给 django 处理,这显然是更好的。很多文章说的「直接把 USE_TZ 设成 False」属于把结界拆了图省事,不推荐。
问题与修复
但设置之后,django 对 mysql 查询会报错:
ValueError: Database returned an invalid datetime value. Are time zone definitions for your database installed?
这是 mysql 没有安装时区表导致的,需要手动同步时区信息到 mysql:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -D mysql -u root -p
mysql -u root -p -e "flush tables;" mysql
第一条把系统时区表加载进 mysql,第二条刷新 mysql 的表缓存,中间需要输入 root 密码。同步之后再用 django 查询 mysql 就正常了。
本文由 aboom 原创,转载请注明出处。