将日期时间序列化为整数时间戳

ele*_*nso 11 python django-rest-framework

我希望django rest在序列化时不将我的DateTime模型字段转换为字符串日期表示.

response_date = serializers.DateTimeField(source="updated_at")
Run Code Online (Sandbox Code Playgroud)

我希望这个出来

1411880508

并不是

"2014-09-28T05:01:48.123"

Tom*_*tie 15

您将要编写自定义序列化程序字段,如下所示:

class TimestampField(serializers.Field):
    def to_native(self, value):
        epoch = datetime.datetime(1970,1,1)
        return int((value - epoch).total_seconds())
Run Code Online (Sandbox Code Playgroud)

支持您希望继承WritableField并执行的写操作from_native().

  • 如果你得到这个答案并使用DRF 3.x,那么`to_native`方法现在是`to_representation` (8认同)
  • AFAIK 日期时间作为数字存储在数据库中。我希望得到这个数字,而不是遍历查询集中的所有记录。我担心这种方法和我自己的方法都会对性能产生影响。 (2认同)

meg*_*joe 11

REST_FRAMEWORK = {
    # if you want with milliseconds or
    'DATETIME_FORMAT': '%s.%f', 
    # only with seconds
    'DATETIME_FORMAT': '%s', 
}
Run Code Online (Sandbox Code Playgroud)

结果将是REST

1)1517863184.666435

2)1517863249


Log*_*ic1 7

我无法让Tom的例子工作,似乎价值没有得到修改.然而它给了我一个起点,经过一些阅读后我发现了一种产生预期结果的方法:

[方法1]

serializers.py

import time

class TimestampField(serializers.Field):
    def to_representation(self, value):
        return int(time.mktime(value.timetuple()))

class MySerializer(serializers.ModelSerializer):
    ts = TimestampField(source="my_fieldname") #Source must be a models.DateTimeField

    class Meta:
        model = myModel
        fields = ('id', 'ts')
Run Code Online (Sandbox Code Playgroud)

JSON输出:

[{
    "id": 1,
    "ts": 1475894303
},
{
    "id": 2,
    "ts": 1475833070 
}]
Run Code Online (Sandbox Code Playgroud)

[方法2]

Tom的解释和之前提到的方法肯定更符合维护标准(因为结果实际上是整数类型).

但是,快速而肮脏的解决方案是指定DateTimeFieldformat参数,并将其设置为以秒为单位显示值.

请注意,这可能无法在Windows机器上正常工作! 并且可能导致ValueError:格式字符串无效

要尝试一下,只需在序列化器字段中包含"format"关键字参数,如下所示:

serializers.py

class MySerializer(serializers.ModelSerializer):    
    timestamp = serializers.DateTimeField(format="%s")

    class Meta:
        model = myModel
        fields = ('id', 'ts')
Run Code Online (Sandbox Code Playgroud)

JSON输出:

[{
    "id": 1,
    "ts": "1475890361"
},
{
    "id": 2,
    "ts": "1475833070"
}]
Run Code Online (Sandbox Code Playgroud)

另外,您可以包括微秒:

timestamp = serializers.DateTimeField(format="%s.%f")
Run Code Online (Sandbox Code Playgroud)

如果要在自己的解释器中测试功能(以验证操作系统是否支持%s参数),只需复制以下行:

import datetime
print datetime.datetime.now().strftime('%s') #datetime formatted as seconds for REST

import time  #This is just for confirmation
print time.mktime(datetime.datetime.now().timetuple()) #time object result as float
Run Code Online (Sandbox Code Playgroud)

我觉得这个方法是用有机磷农药的问题有点不一致的,因为结果是不实际整数类型,而不是它是一个整数/浮点的字符串表示 - 和REST将切切实实的周围添加值引号.

  • 这应该是公认的答案。format="%s" 更简洁! (2认同)