天天看點

Django–ORM查詢-時間比對Django–ORM查詢-時間比對

文章目錄

  • Django--ORM查詢-時間比對
    • 1. 引入
    • 2. 查錯
    • 3. 解決
    • 4. 知識補充

Django–ORM查詢-時間比對

1. 引入

帥帥的我遇到了一個問題,我需要從

Student

表中,取出建立時間

c_time

2019-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

調用的是

mysql

DATE

方法,若覺得中間容易出錯,在邏輯允許情況下可更改字段

同栗,檢視建立時間

c_time

2019-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是最強的

我是最帥的