天天看點

Django中的日期處理注意事項和自定義時間格式轉換

我們在用django建立models時,常常會涉及時間日期字段的處理,django裡日期相關field有datetimefield、datefield和timefield三種類型,看似簡單,但其中有一些容易出錯的地方需要注意;另外,如果不習慣django的預設時間格式,也可以自定義的修改。

datetimefield、datefield和timefield,其值分别對應着python裡的datetime.datetime、datetime.date和datetime.time三個執行個體,這三個field裡都有兩個參數:auto_now和auto_now_add,預設值均為false。

auto_now參數說明:

每次儲存對象時自動将字段值設定為目前時間,能夠在儲存該字段時,将其值設定為目前時間,并且每次修改model,都會自動更新。是以這個參數在需要存儲“最後修改時間”的場景下,十分友善,常用類似“last-modified”或者"update_time"字段。

需要注意的是,該字段不能被手動修改覆寫;當設定為true時,隻有每次調用model.save()時,才會強制更新為目前時間點;當用其他方式更新其他字段時并不會更新:比如用queryset.update()方法,即使為該字段指定一個自定義的值,該字段也不會有所更改。比較直覺的表現形式是,如果使用django自帶的admin管理器,那麼該字段在admin中是隻讀的,并且無法進行修改。示例代碼如下:

datacenter的modeladmin代碼:

admin界面效果圖:

Django中的日期處理注意事項和自定義時間格式轉換

點選編輯頁面,會發現找不到‘更新時間’的編輯處,因為此字段是隻讀,且不允許手動修改,效果圖如下:

Django中的日期處理注意事項和自定義時間格式轉換

當頁面“save”之後,再觀察現在的‘更新時間’發現時間已經被修改:

Django中的日期處理注意事項和自定義時間格式轉換

auto_now_add參數說明:

設定為true時,會在model對象第一次被建立時,将字段的值設定為建立時的時間,以後修改對象時,字段的值不會再更新。該屬性通常被用在存儲“建立時間”的場景下。與auto_now類似,auto_now_add也具有強制性,一旦被設定為true,就無法在程式中手動為字段指派,在admin中字段也會成為隻讀的。

繼續沿用剛才的代碼示例,'update_time'的'auto_now'改完'auto_now_add',其他代碼不變:

編輯更新北京聯通機房的ip位址段之後儲存:

Django中的日期處理注意事項和自定義時間格式轉換

更改之後‘更新時間’并未發生改變(見下圖),因為‘auto_now_add’在對象建立完成後即不再更新:

Django中的日期處理注意事項和自定義時間格式轉換

如何實作可編輯

auto_now和auto_now_add被設定為true後,這樣做會導緻字段成為editable=false和blank=true的狀态。editable=false将導緻字段不會被呈現在admin中,blank=ture表示允許在表單中不輸入值。此時,如果在admin的fields或fieldset中強行加入該日期時間字段,那麼程式會報錯,admin無法打開;如果在admin中修改對象時,想要看到日期和時間,可以将日期時間字段添加到admin類的readonly_fields中:

<code>readonly_fields = ('save_date', 'mod_date',)</code>

那麼問題來了。實際場景中,往往既希望在對象的建立時間預設被設定為目前值,又希望能在日後修改它。怎麼實作這種需求呢?

django中所有的model字段都擁有一個default參數,用來給字段設定預設值。可以用default=timezone.now來替換auto_now=true或auto_now_add=true。timezone.now對應着django.utils.timezone.now(),代碼示例:

這裡'update_time'字段預設值改為timezone.now()後,再次編輯已經能看到相應‘更新時間’字段,并且可修改:

Django中的日期處理注意事項和自定義時間格式轉換

我們把時間天數加1天後,儲存退出再觀察‘更新時間’已經變為自定義時間:

Django中的日期處理注意事項和自定義時間格式轉換

自定義日期格式:

剛建立的django應用,可能你看到的日期顯示格式跟下圖類似(跟language_code和time_zone有關):

如果不習慣這種格式,自己定義顯示格式的配置如下,更改django的setting.py檔案:

注意事項:如果use_l10n設定為了true,那麼語言環境規定的格式具有更高的優先級并将被應用,即date_format不生效。

這裡可用的格式化字元串的其他寫法參見django官方文檔:

&lt;https://docs.djangoproject.com/en/2.0/ref/templates/builtins/#date&gt;;

available format strings,部分截圖:

Django中的日期處理注意事項和自定義時間格式轉換
Django中的日期處理注意事項和自定義時間格式轉換

另外在django頁面渲染的時候,html頁面從資料庫中讀出datetimefield字段時,顯示的時間格式和資料庫中存放的格式不一緻,另外一個解決辦法:可以在頁面格式化時間,添加{{ datacenter.updatetime|date:"y-m-d h:i:s" }}類似的過濾器。之後重新整理頁面,即可正常顯示。

相關文檔:

https://docs.djangoproject.com/en/2.0/ref/settings/

https://docs.djangoproject.com/en/2.0/ref/templates/builtins/#std:templatefilter-date