django中的filter日期查询属性有:year、month、day、week_day、hour、minute、second
但是但我在使用过滤查询是却总是无法过滤出月份,各种查资料,最后才发现是时区问题,django查询数据库时对应的ORM语句会用使用mysql自带的一些时间处理函数如convert_tz(时间转换函数),而mysql无法获取Asia/Shanghai的正确时间,查询的时候返回空列表。
--记录一下排查过程:
*查看mysql日志文件,看Django查询数据时的ORM语句
- 打开mysql.cnf配置文件,注释掉68 69行:【环境是ubuntu】
sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
- 重启mysql服务
sudo service mysql restart
- 查看日志
sudo tail -f /var/log/mysql/mysql.log
# Linux命令:tail命令: 默认会显示文件的末尾,可以动态查看文件新加入的数据
*在另外一个终端进行django语句的执行:
>>> p = Post.objects.filter(publish__year=2018,slug="view") #测试过滤年份,获取一条数据
>>> p
[<Post: 使用基于类的试图>]
可以看到得到的日志如下:
>>> c = Post.objects.filter(publish__month=4,slug="view") >>> c [] #还没解决时区问题的情况下是返回空的,所以在有可能在渲染页面时不能获得数据
解决方法是在终端输入:
# MySQL安装程序在mysql数据库中创建时区表,但不装载。所以必须手动装载
mysql_tzinfo_to_sql /usr/share/zoneinfo
# 然后重启数据库
service mysql restart
然后重新进入Django shell过滤数据,即可查得月份的数据
这个方法也可以处理mysql设置时区时报错的问题
使用SET GLOBAL time_zone = 'Asia/Shanghai'; 命令设置时区
会却报错ERROR 1298 (HY000): Unknown or incorrect time zone: 'Asia/Shanghai'。
mysql默认的时区格式并不支持这种,而是写成 set time_zone='+8:00';这种格式,如果想要使用'Asia/Shanghai'的格式
就要用mysql_tzinfo_to_sql程序用来装载时区表,也是在终端命令行输入如下命令,跟上面的一样
mysql_tzinfo_to_sql /usr/share/zoneinfo #第一种(一般第一种就可以了,推荐)
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -uroot mysql #第二种
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -uroot --force mysql #第三种
---了解,django中的时区问题
django中有两个时间概念:naive time 与 active time。
naive time:就是不带时区的时间,
Active time就是带时区的时间。
还有一个就是UTC时间,UTC时间表示的是格林尼治平均时即可,即零区时间
datetime模块是python自带的包,timezone是django内的工具包,
from datetime import date,datetime
from django.utils import timezone
使用datetime.datetime.utcnow()、datetime.datetime.now()输出的类似2015-05-11 09:10:33.080451就是不带时区的时间(naive time),而使用django.utils.timezone.now()输出的类似2015-05-11 09:05:19.936835+00:00的时间就是带时区的时间(Active time),其中+00:00表示的就是时区相对性。