2013-06-26 7 views
19

Buduję aplikację, która będzie służyć ludziom znajdującym się w różnych miejscach na całym świecie.
Używam Django-Rest-Framwork do komunikacji między klientami a serwerem.
Wszystkie wartości DateTime są zapisywane w DB jako UTC (mam USE_TZ = True i TIME_ZONE = 'Greenwich' w settings.py).Django-rest-framework renderers/parsery świadomy świadomy ramek

Otrzymam od użytkownika jego/jej lokalną strefę czasową.

Aby Test DRF dla świadomości czasowej Napisałem ten middleware ze stałej czasowej:

import pytz 
from django.utils import timezone 

class TimezoneMiddleware(object): 
    def process_request(self, request): 
     timezone.activate(pytz.timezone("Asia/Jerusalem")) 

Problem brzmi:
Mam przypadek, w którym dostaję od "START_TIME" użytkownika i Pola "end_time" zawierają czasy w strefie czasowej użytkownika, która przechodzi przez UnicodeJSONRenderer do , a następnie zapisana w DB. Są one jednak zapisywane jako , tak jakby były w UTC.

W tym miejscu można oczekiwać, że serializator (lub analizator składni) traktuje dane wejściowe datetime od użytkownika jako datetime, które muszą zostać przekonwertowane z "Asia/Jerusalem" na UTC przed zapisaniem do DB, ponieważ wykonałem timezone.activate(pytz.timezone("Asia/Jerusalem")).

To samo dotyczy danych analizowanych w odpowiedzi poprzez JSONParser.
Oczekując, że pola DateTime w zwróconym pliku JSON będą znajdować się w strefie czasowej aktywowanej w oprogramowaniu pośredniczącym, są zwracane jako UTC.

Jak mogę to łatwo osiągnąć w DRF?

+0

Znalazłeś rozwiązanie? – yakxxx

+0

@yakxxx - Niestety jeszcze nie. Na razie otrzymuję i zwracam wartości datetime w GMT, a konwersja do lokalnej strefy czasowej odbywa się po stronie klienta. – OrPo

+0

Czy możesz wysłać prośbę? Zastanawiam się, którego formatu używałeś w JSON? Czy używasz łańcucha ISO 8601 ze strefą czasową? – codingjoe

Odpowiedz

31

miałem ten sam problem i rozwiązać go poprzez dodanie nowego typu pola:

class DateTimeTzAwareField(serializers.DateTimeField): 

    def to_native(self, value): 
     value = timezone.localtime(value) 
     return super(DateTimeTzAwareField, self).to_native(value) 

i teraz można go używać w ModelSerializer:

class XSerializer(serializers.ModelSerializer): 
    start = DateTimeTzAwareField() 
    end = DateTimeTzAwareField() 

    class Meta: 
     model = XModel 
     fields = (
      'id', 
      'start', 
      'end', 
     ) 
+3

Jedna mała poprawka - jeśli to pole może mieć wartość zerową, wymagana jest prosta kontrola, na przykład: 'jeśli wartość: wartość = timezone.localtime (wartość)' – Ophir

+4

Nowy Django-Rest-Framework, zamiast tego użyj 'to_representation' 'to_native' – db0

+0

Działa jak czar, dzięki! –

14

Odpowiedź przez @yakxxx wydaje się być najlepszym rozwiązaniem. jestem delegowania go ponownie po zaktualizowaniu go do pracy z nowszymi wersjami restframework

wewnątrz mojego katalogu (wspólne/serializers.py)

from rest_framework import serializers 
from django.utils import timezone 

class DateTimeFieldWihTZ(serializers.DateTimeField): 

    def to_representation(self, value): 
     value = timezone.localtime(value) 
     return super(DateTimeFieldWihTZ, self).to_representation(value) 

w mojej aplikacji

from common.serializers import DateTimeFieldWihTZ 

class MyObjectSerializer(serializers.ModelSerializer): 

    start = DateTimeFieldWihTZ(format='%d %b %Y %I:%M %p') 
    end = DateTimeFieldWihTZ(format='%d %b %Y %I:%M %p') 
+0

Nie trzeba sprawdzać, czy wartość jest pusta, jak sugeruje Ophir. Wygląda na to, że jeśli wartość jest pusta, ta metoda nigdy nie będzie wywoływana. – Ramast

+0

Czy mogę ustawić 'DEFAULT_DATETIME_PARSER = 'common.serializers. DateTimeFieldWihTZ ', aby zmienić wszystkie DatetimeField na DateTimeFieldWihTZ? – kxxoling

+1

Nie jestem świadomy żadnego ustawienia ramowego odpoczynku z tą nazwą – Ramast

Powiązane problemy