Django REST Framework中把DatetimeField转换为时间戳
2019-07-21 15:32:11 +08 字数:870 标签: Django目的 ¶
普通DateTimeField会在Django REST Framework中输出的JSON中,转换成字符串的形式,如"2019-06-10T00:49:51.689440+08:00"。
并且也只接受对应格式字符串的输入。
这对DateField也许还比较方便,但对DateTimeField来说是不可接受的。
DateTimeField只需要在显示时,由客户端(浏览器或移动App)转换为字符串,而传输时则最好是一个float。
否则,客户端会需要比较复杂的日期与时区转换操作,传输的数据量也比较大。
本文介绍如何利用Django REST Framework中的自定义Feild,把存储层的datetime转换为float形式的timestamp。
其它方案 ¶
通过格式化,可以直接做到DateTimeField转换为Timestamp形式的字符串,比如"1560098991.689440"。
但是却无法做到识别这种字符串的输入,造成输入输出的不均衡。
在settings.py中添加:
REST_FRAMEWORK = {
'DATETIME_FORMAT': '%s.%f',
'DATETIME_INPUT_FORMATS': ['%s.%f', 'iso-8601'],
}
这里输出虽然是1560098991.689440,但是输入却必须是ISO 8601标准的"2019-06-10T00:49:51.689440+08:00"。
那个'%s.%f',输出时没问题,输入时却会被解析为ss.uuuuuu的形式,丢失了秒以上的信息。
也就是说,只能输入"91.689440"这种字符串,时间当然不对。
可行方案 ¶
利用Django REST Framework中的自定义Field,可以在存储层的datetime和表现层的timestamp之间做转换。
Model样例 ¶
from django.db.models import DateTimeField, Model
class Example(Model):
datetime = DateTimeField()
Serializers ¶
from datetime import datetime
from pytz import timezone
from rest_framework.serializers import Field, HyperlinkedModelSerializer
from ..settings import TIME_ZONE
class TimestampField(Field):
"""
This serializer field transform a datetime str to a timestamp float.
"""
def to_representation(self, value):
return value.timestamp()
def to_internal_value(self, data):
timestamp = float(data)
no_tz = datetime.utcfromtimestamp(timestamp)
return no_tz.astimezone(timezone(TIME_ZONE))
class ExampleSerializer(HyperlinkedModelSerializer):
timestamp = TimestampField(source='datetime')
class Meta:
model = Frame
fields = (
'url',
'timestamp',
)
如果不在datetime中放入时区信息,则会有以下警告:
RuntimeWarning: DateTimeField Frame.datetime received a naive datetime (2019-06-09 16:49:51.689440) while time zone support is active.