2014-09-28 2 views
8

Я бы хотел, чтобы django rest не преобразовал мое поле модели DateTime в строковое представление даты при его сериализации.Сериализовать datetime как целочисленную временную метку

response_date = serializers.DateTimeField(source="updated_at") 

Я хотел бы, чтобы выйти, как

1411880508

и не

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

ответ

8

Вы хотите написать custom serializer field, например, так:

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

Чтобы поддерживать операции записи, которые вам нужны унаследовать от WritableField, а также реализовать from_native().

+1

AFAIK в DateTime хранится в базе данных в виде числа , Я надеялся получить это число вместо того, чтобы перебирать все записи в наборе запросов. Я боюсь, что будут последствия для производительности как для этого, так и для моего собственного подхода. – elewinso

+3

Если вы пришли к этому ответу и используете DRF 3.x, метод 'to_native' теперь' to_representation' –

1

Хотя я предпочитаю ответ, данный Томом Кристи, поскольку он более надежный. я решил опубликовать свое решение в пользу потенциальных читателей

response_date = serializers.SerializerMethodField('get_timestamp') 
def get_timestamp(self, obj): 
    #times 1000 for javascript. 
    return time.mktime(obj.updated_at.timetuple()) * 1000 
3

я не смог получить пример Тома работать, и это, казалось, значения не были изменены. Однако это дало мне отправную точку и после некоторого чтения я нашел способ получения желаемого результата:

[Способ 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') 

JSON выход:

[{ 
    "id": 1, 
    "ts": 1475894303 
}, 
{ 
    "id": 2, 
    "ts": 1475833070 
}] 

[Способ 2]

Объяснение Тома и предыдущий метод, безусловно, более соответствуют трекам с поддержанием стандартов (поскольку результаты на самом деле имеют тип integer).

Однако быстрое и грязное решение заключается в том, чтобы указать format parameter for the DateTimeField и установить его для отображения значения в секундах.

Обратите внимание, что это, вероятно, не будет работать на машинах Windows! И может привести к ValueError: Недопустимая строка формата

Чтобы попробовать его просто включить «формат» параметр ключевого слова в вашем поле сериализатора следующим образом:

сериализаторы.пй выход

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

    class Meta: 
     model = myModel 
     fields = ('id', 'ts') 

JSON:

[{ 
    "id": 1, 
    "ts": "1475890361" 
}, 
{ 
    "id": 2, 
    "ts": "1475833070" 
}] 

Кроме того, вы можете включать в себя микросекунды:

timestamp = serializers.DateTimeField(format="%s.%f") 

Если вы хотите, чтобы проверить функциональность в вашем собственном интерпретаторе (для проверки ОС поддерживает % 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 

Я чувствую, что этот метод немного несовместим с вопросом OPs, потому что результат не имеет значения типа integer, а представляет собой строковое представление целого числа/float - и REST будет излишне добавлять кавычки вокруг значения.

2

глобальной конфигурации:

REST_FRAMEWORK = { 
    'DATETIME_FORMAT': '%s.%f', 
} 
0
REST_FRAMEWORK = { 
    # if you want with milliseconds or 
    'DATETIME_FORMAT': '%s.%f', 
    # only with seconds 
    'DATETIME_FORMAT': '%s', 
} 

результат REST будет

1) 1517863184,666435

2) 1517863249

Смежные вопросы