Django–ORM查询-时间匹配

文章目录

  • Django--ORM查询-时间匹配
    • 1. 引入
    • 2. 查错
    • 3. 解决
    • 4. 知识补充

Django–ORM查询-时间匹配

1. 引入

帅帅的我遇到了一个问题,我需要从Student表中,取出创建时间c_time2019-3-20的记录。

  1. 首先我们确认c_time类型

    In [5]: s1 = Student.objects.get(name='灰原')                                    
    
    In [6]: type(s1.c_time)                                                          
    Out[6]: datetime.datetime
    

  2. 再查看表内数据

    In [10]: Student.objects.all()                                                   
    Out[10]: <QuerySet [
        <Student: id<1>name[柯南]gender()age|16|c_time:2019-03-20 15:25:09+00:00>, 
        <Student: id<2>name[元太]gender()age|16|c_time:2019-03-20 15:26:16+00:00>, 
        <Student: id<3>name[萨斯给]gender()age|16|c_time:2019-03-20 15:27:56+00:00>, 
        <Student: id<4>name[步美]gender()age|16|c_time:2019-03-20 15:28:16+00:00>, 
        <Student: id<5>name[灰原]gender()age|16|c_time:2019-03-20 15:28:16+00:00>, 
        <Student: id<8>name[纳鲁淘]gender()age|16|c_time:2019-03-20 15:28:16+00:00>
        ...
    ]>
    
    
    • 创建日期在2019-3-20数据不少

2. 查错

  1. 查询
In [11]: Student.objects.filter(c_time__date=datetime.date(2019, 3, 20))         
Out[11]: <QuerySet []>

In [12]: s1.c_time.date()==datetime.date(2019, 3, 20)                            
Out[12]: True    

  • 查询结果为空
  • 有满足条件记录

  1. 对比
In [19]: Student.objects.filter(c_time=t1)                                       
Out[19]: <QuerySet [
    <Student: id<4>name[步美]gender()age|16|c_time:2019-03-20 15:28:16+00:00>, 
    <Student: id<5>name[灰原]gender()age|16|c_time:2019-03-20 15:28:16+00:00>,
    ...
]>

In [20]: td1 = t1.date()                                                         

In [21]: Student.objects.filter(c_time__date=td1)                                
Out[21]: <QuerySet []>

  • 发现只有调用__date属性出错

  1. 验证
In [22]: r1 = Student.objects.filter(c_time=t1)                                  

In [23]: str(r1.query)                                                           
Out[23]:''' 
    SELECT `book_student`.`id`, `book_student`.`name`, `book_student`.`age`,    		    	`book_student`.`gender`, `book_student`.`c_time`, `book_student`.`college_id`
    FROM `book_student` 
    WHERE `book_student`.`c_time` = 2019-03-20 15:28:16'
    '''
    
In [24]: r2 = Student.objects.filter(c_time__date=td1)                           

In [26]: str(r2.query)                                                           
Out[26]: '''
SELECT `book_student`.`id`, `book_student`.`name`, `book_student`.`age`, `book_student`.`gender`, `book_student`.`c_time`, `book_student`.`college_id` 
FROM `book_student` 
WHERE DATE(CONVERT_TZ(`book_student`.`c_time`, 'UTC', 'Asia/Shanghai')) = 2019-03-20
'''

  • CONVERT_TZ(dt,from_tz,to_tz):转换datetime值dt,从 from_tz 由给定转到 to_tz 时区给出的时区,并返回的结果值。 如果参数无效该函数返回NULL。

  1. 测试sql
mysql> SELECT CONVERT_TZ('20190320000000', 'UTC', 'Asia/Shanghai');
+------------------------------------------------------+
| CONVERT_TZ('20190320000000', 'UTC', 'Asia/Shanghai') |
+------------------------------------------------------+
| null                                |
+------------------------------------------------------+
1 row in set (0.00 sec)

  • 找到了问题,我的MySQL数据库应用的mysql(即系统自带的那个数据库)数据库中没有对应的time_zone表
  • 解决方法请参阅:2lovecode的博客

3. 解决

  1. 验证sql
mysql> SELECT CONVERT_TZ('20190320000000', 'UTC', 'Asia/Shanghai');
+------------------------------------------------------+
| CONVERT_TZ('20190320000000', 'UTC', 'Asia/Shanghai') |
+------------------------------------------------------+
| 2019-03-20 08:00:00                                  |
+------------------------------------------------------+
1 row in set (0.00 sec)

配置好后,sql 验证通过


  1. 验证orm
In [32]: Student.objects.filter(c_time__date=datetime.date(2019, 3, 20)).count() 
Out[32]: 8

In [33]: Student.objects.filter(c_time__date='2019-03-20').count()               
Out[33]: 8

通过验证,大吉大利,晚上加餐。


4. 知识补充

c_time__date调用的是mysqlDATE方法,若觉得中间容易出错,在逻辑允许情况下可更改字段

同栗,查看创建时间c_time2019-3-20的记录数目。

In [38]: res = Student.objects.filter(c_time__startswith='2019-03-20')           

In [39]: res.count()                                                             
Out[39]: 8

In [40]: str(res.query)                                                          
Out[40]: 'SELECT `book_student`.`id`, `book_student`.`name`, `book_student`.`age`, `book_student`.`gender`, `book_student`.`c_time`, `book_student`.`college_id` FROM `book_student` WHERE `book_student`.`c_time` LIKE BINARY 2019-03-20%'

或者

In [42]: res = Student.objects.filter(c_time__contains='2019-03-20')             

In [43]: res.count()                                                             
/home/zdq/.virtualenvs/djfirst/lib/python3.5/site-packages/pymysql/cursors.py:170: Warning: (1292, "Incorrect datetime value: '%2019-03-20%' for column 'c_time' at row 1")
  result = self._query(query)
Out[43]: 8
# 哎呀,警告了,看来要慎用

亦或者

In [18]: res = Student.objects.filter(c_time__range=('2019-03-20 00:00:00', '2019
    ...: -03-21 00:00:00')) 
                                                     
In [19]: str(res.query)                                                          
Out[19]: 'SELECT `book_student`.`id`, `book_student`.`name`, `book_student`.`age`, `book_student`.`gender`, `book_student`.`c_time`, `book_student`.`college_id` FROM `book_student` WHERE `book_student`.`c_time` BETWEEN 2019-03-19 16:00:00 AND 2019-03-20 16:00:00'

In [20]: res.count()                                                             
Out[20]: 8

  • 会发出警告:time zone support is active.RuntimeWarning
  • sql 是使用UTC时间的,不难看出sql语句时间区间提前6小时。

从不同角度,使用不同的方法,不同方法的优劣这些都是语言的美丽了。

墨染是最棒的

Tuple是最强的

我是最帅的

你可能感兴趣的:(Django,Django,匹配条件,时间字段,异常)