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

28 篇文章 1 订阅
4 篇文章 0 订阅

关于 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中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值