django naive datetime問題

进取發表於2024-11-16

naive datetime問題,其實就是datetime資料沒有攜帶時間就傳遞給了模型類

現象:
D:\anaconda3\envs\schedule_devops\lib\site-packages\django\db\models\fields_init_.py:1367: RuntimeWarning: DateTimeField NodeStopRecord.stop_time received a naive datetime (2024-11-16 02:34:07.905087) while time zone support is active.
warnings.warn("DateTimeField %s received a naive datetime (%s)"

一番摸索發現: 當我們在django settings.py 中配置了 LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' USE_TZ = True 以後,也就是啟動了django 自動實現utc時間和本地時間轉換機制以後,正常情況下我們從頁面操作的資料儲存到資料中,時間和日期自動會儲存為utc時間和日期(比本地時間 -8h)。但是,如果我們自己寫的程式碼往資料庫中插入資料,呼叫ORM 模型類傳遞了沒有時區的datetime 就會報上面的錯誤。模型類會提示我們 django 模型接收到了一個沒有時區的datetime,簡稱(naive datetime),模型類期望接收aware datetime 時間(有時區的datetime)。雖然,模型類不會強制限制我們,當我們傳遞了 naive datetime 時間以後也是會正常儲存到資料中,只不過會發警告提示我們。我就是強迫症,看到一堆標紅的警告不太舒服。那解決呢,也簡單就是我們給datetime 加上時區資訊在傳遞給模型類就不會有紅色提示資訊了。

我的模型類
class NodeStopRecord(models.Model):
    """
    暫停記錄
    """
    node_name = models.CharField(max_length=20, verbose_name='節點英文名')
    node_status = models.SmallIntegerField(verbose_name="節點狀態")
    stop_time = models.DateTimeField(verbose_name='暫停時間')
    run_time = models.DateTimeField(verbose_name='開啟時間', null=True)
    create_time = models.DateTimeField(auto_now_add=True, verbose_name="建立時間")
    update_time = models.DateTimeField(auto_now=True, verbose_name="更新時間")


使用 python manage.py shell 給資料庫新增幾條資料
>>> naive_datetime = datetime.now() 
>>>
>>> naive_datetime                                                                              
datetime.datetime(2024, 11, 16, 11, 13, 39, 741807)  

>>> NodeStopRecord.objects.create(node_name='h123',node_status=100, stop_time=naive_datetime)   
D:\anaconda3\envs\schedule_devops\lib\site-packages\django\db\models\fields\__init__.py:1367: RuntimeWarning: DateTimeField NodeStopRecord.stop_time received a naive datetime (2024-11-16 11:13:39.741807) while time zone support is active.
  warnings.warn("DateTimeField %s received a naive datetime (%s)"
<NodeStopRecord: NodeStopRecord object (533)>
報錯出現了

給datetime 加上時區傳遞給模型類
>>> import pytz
>>> tz = pytz.timezone('Asia/Shanghai')
>>> aware_datetime = tz.localize(naive_datetime)  
>>>
>>> aware_datetime
datetime.datetime(2024, 11, 16, 11, 13, 39, 741807, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>)
>>> NodeStopRecord.objects.create(node_name='x123',node_status=101, stop_time=aware_datetime)  
<NodeStopRecord: NodeStopRecord object (535)>
向資料據插入資料,報錯消失了

去資料庫查詢資料
mysql> select * from nodestoprecord where node_status >= 100;
+-----+-----------+-------------+----------------------------+----------+----------------------------+----------------------------+
| id  | node_name | node_status | stop_time                  | run_time | create_time                | update_time                |
+-----+-----------+-------------+----------------------------+----------+----------------------------+----------------------------+
| 533 | h123      |         100 | 2024-11-16 03:13:39.741807 | NULL     | 2024-11-16 03:14:48.018860 | 2024-11-16 03:14:48.018860 |
| 535 | x123      |         101 | 2024-11-16 03:13:39.741807 | NULL     | 2024-11-16 03:17:59.670702 | 2024-11-16 03:17:59.670702 |
+-----+-----------+-------------+----------------------------+----------+----------------------------+----------------------------+
2 rows in set (0.00 sec)

相關文章