datetime 的 isoformat 和 DRF 序列化類的 DateTimeField 的 to_representation 和 auto_now

關於 datetime 的 isoformat ,研究這個的契機是:
工單系統後天改造中發現:該項目中數據庫存儲的什麼值,接口返回的就是什麼值,仔細理解這句話(這跟歸檔項目的行爲不一致,歸檔系統的數據庫中存儲的是 UTC 時區的時間,但是接口返回的是東八區時間,參數基本一樣 TIME_ZONE = ‘Asia/Shanghai’ USE_TZ = True ,後來發現因爲在歸檔系統的序列化類裏的 DateTimeField 的 to_representation 函數中調用了 enforce_timezone 函數
1.DateTimeField 的 to_representation

D:\...\archiver_gitcode\venv\Lib\site-packages\rest_framework\fields.py

class DateTimeField(Field):
    ... ...
    def enforce_timezone(self, value):
        """
        When `self.default_timezone` is `None`, always return naive datetimes.
        When `self.default_timezone` is not `None`, always return aware datetimes.
        """
        field_timezone = getattr(self, 'timezone', self.default_timezone())

        if field_timezone is not None:
            if timezone.is_aware(value):
                try:
                    return value.astimezone(field_timezone)
                except OverflowError:
                    self.fail('overflow')
            try:
                return timezone.make_aware(value, field_timezone)
            except InvalidTimeError:
                self.fail('make_aware', timezone=field_timezone)
        elif (field_timezone is None) and timezone.is_aware(value):
            return timezone.make_naive(value, utc)
        return value


    def to_representation(self, value):
        if not value:
            return None

        output_format = getattr(self, 'format', api_settings.DATETIME_FORMAT)

        if output_format is None or isinstance(value, six.string_types):
            return value

        value = self.enforce_timezone(value)    ------------在低版本的 DRF 裏面沒有這句話--------------

        if output_format.lower() == ISO_8601:
            value = value.isoformat()
            if value.endswith('+00:00'):
                value = value[:-6] + 'Z'
            return value
        return value.strftime(output_format)

import datetime
from dateutil import tz
from django.utils.timezone import make_aware, is_aware, is_naive
print '----------get the ISO format------------'
value = datetime.datetime.now()
print value, type(value)
if is_naive(value):
    print 'value is NOT aware time'
isoforamt = value.isoformat()
print isoforamt, type(isoforamt)



tz_sh = tz.gettz('Asia/Shanghai')
now_sh = datetime.datetime.now(tz=tz_sh)
print now_sh, type(now_sh)
if is_aware(now_sh):
    print 'now_sh is aware time'

運行結果:

----------get the ISO format------------
2020-03-20 21:49:24.225000 <type 'datetime.datetime'>
value is NOT aware time
2020-03-20T21:49:24.225000 <type 'str'>
2020-03-20 21:49:24.370000+08:00 <type 'datetime.datetime'>
now_sh is aware time

2.DateTimeField 的 auto_now_add 和 auto_now

auto_now_add: 這個參數的默認值也爲False,設置爲True時,會在model對象第一次被創建時,將字段的值設置爲創建時的時間,以後修改對象時,字段的值不會再更新。該屬性通常被用在存儲“創建時間”的場景下。與auto_now類似,auto_now_add也具有強制性,一旦被設置爲True,就無法在(創建對象的)程序中手動爲字段賦值,在admin中字段也會成爲只讀的。如果是先 filter 出已有的對象,然後對 create_time 字段賦值保存,是可以的。

auto_now: 這個參數的默認值爲false,設置爲true時,能夠在保存該字段時,將其值設置爲當前時間,並且每次修改model,都會自動更新。因此這個參數在需要存儲“最後修改時間”的場景下,十分方便。需要注意的是,設置該參數爲true時,並不簡單地意味着字段的默認值爲當前時間,而是指字段會被“強制”更新到當前時間,你無法程序中手動爲字段賦值;如果使用django再帶的admin管理器,那麼該字段在admin中是隻讀的。

auto_now和auto_now_add被設置爲True後,這樣做會導致字段成爲editable=False和blank=True的狀態。editable=False將導致字段不會被呈現在admin中,blank=Ture表示允許在表單中不輸入值。此時,如果在admin的fields或fieldset中強行加入該日期時間字段,那麼程序會報錯(參考HelloNG 的StudentAdmin),admin無法打開;如果在admin中修改對象時,想要看到日期和時間,可以將日期時間字段添加到admin類的readonly_fields中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章