2014-09-28 5 views
8

Vorrei che django rest non convertisse il campo del mio modello DateTime in una reprostazione della data della stringa durante la serializzazione.serializza un datetime come un timestamp intero.

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

Vorrei che questo a venire fuori come

1411880508

e non

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

risposta

8

Avrai voglia di scrivere un custom serializer field, in questo modo:

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

Per supportare le operazioni di scrittura che desideri ereditare da WritableField e implementare anche from_native().

+1

per quanto ne so il datetime viene memorizzato nel database come un numero . Speravo di ottenere quel numero invece di dover eseguire iterazioni su tutti i record nel queryset. Temo che ci saranno implicazioni sulla performance sia per questo che per il mio approccio. – elewinso

+3

Se si arriva da questa risposta e si utilizza DRF 3.x, il metodo 'to_native' è ora' to_representation' –

1

Anche se preferisco la risposta data da Tom Christie in quanto è più robusta. ho deciso di pubblicare la mia soluzione a beneficio dei potenziali lettori

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

non ero in grado di ottenere esempio di Tom al lavoro e sembrava i valori non venivano modificati. Tuttavia mi ha dato un punto di partenza e dopo un po 'la lettura ho trovato un modo per produrre il risultato desiderato:

[METODO 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') 

uscita JSON:

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

[METODO 2]

La spiegazione di Tom e il metodo sopra menzionato sono decisamente più in linea con il mantenimento degli standard (poiché i risultati sono in realtà di tipo intero).

Tuttavia una soluzione rapida e sporca è specificare il format parameter for the DateTimeField e impostarlo per mostrare il valore in secondi.

Nota che probabilmente non funzionerà correttamente su macchine Windows! e può comportare un ValueError: stringa di formato non valido

Per provarlo basta includere il parametro "formato" parola chiave nel campo serializzatore in questo modo:

serializzatori.py uscita

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" 
}] 

Inoltre è possibile includere microsecondi:

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

Se si desidera verificare la funzionalità nel proprio interprete (per verificare il sistema operativo supporta la % s parametro) copia semplicemente su queste righe:

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 

Ritengo che questo metodo sia un po 'incoerente con la domanda OP perché il risultato non è in realtà di tipo intero, ma è una rappresentazione di stringa di un intero/float - e REST aggiungerà sgarbatamente quotazioni attorno al valore.

2

globale Configurazione:

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', 
} 

risultato nel resto sarà

1) 1517863184,666435

2) 1517863249