解决-Django使用filter过滤时间,无法获取月份的问题

django中的filter日期查询属性有:year、month、day、week_day、hour、minute、second

但是但我在使用过滤查询是却总是无法过滤出月份,各种查资料,最后才发现是时区问题,django查询数据库时对应的ORM语句会用使用mysql自带的一些时间处理函数如convert_tz(时间转换函数),而mysql无法获取Asia/Shanghai的正确时间,查询的时候返回空列表。

--记录一下排查过程:

*查看mysql日志文件,看Django查询数据时的ORM语句

  1. 打开mysql.cnf配置文件,注释掉68 69行:【环境是ubuntu】
    sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf

  2. 重启mysql服务
    sudo  service mysql restart
  3. 查看日志
    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表示的就是时区相对性。

原文地址:https://www.cnblogs.com/panlq/p/8868108.html