2013-06-26 38 views
19

Tôi đang xây dựng một ứng dụng sẽ phục vụ mọi người ở những nơi khác nhau trên thế giới.
Tôi đang sử dụng Django-Rest-Framwork cho giao tiếp giữa khách hàng và máy chủ.
Tất cả giá trị Ngày giờ được lưu vào DB dưới dạng UTC (Tôi có USE_TZ = TrueTIME_ZONE = 'Greenwich' trong settings.py).Trình hiển thị/trình phân tích cú pháp khung thời gian Django-rest-frame

Tôi sẽ nhận được từ người dùng múi giờ địa phương của họ.

Để kiểm tra DRF cho nhận thức múi giờ tôi đã viết middleware này với múi giờ cố định:

import pytz 
from django.utils import timezone 

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

Vấn đề là:
Tôi có một trường hợp trong đó tôi nhận được từ người sử dụng "start_time" và Các trường "end_time" containting datetimes trong người dùng LOCAL múi giờ của bạn thông qua các UnicodeJSONRenderer đến một ModelSerializer và sau đó được lưu vào DB. Tuy nhiên, chúng được lưu như thể chúng ở trong UTC. Tại thời điểm này tôi mong đợi bộ nối tiếp (hoặc phân tích cú pháp) xử lý đầu vào datetime từ người dùng là datetime cần được chuyển đổi từ "Asia/Jerusalem" sang UTC trước khi lưu vào DB kể từ khi tôi thực hiện timezone.activate(pytz.timezone("Asia/Jerusalem")).

Điều tương tự cũng xảy ra khi dữ liệu được phân tích ngược lại trong phản hồi qua JSONParser.
Trong khi mong đợi các trường DateTime trong JSON trả về nằm trong múi giờ được kích hoạt trong phần mềm trung gian, chúng được trả về dưới dạng UTC.

Tôi có thể dễ dàng đạt được điều đó như thế nào trong DRF?

+0

Bạn đã tìm thấy một dung dịch? – yakxxx

+0

@yakxxx - Thật không may là chưa. Bây giờ tôi nhận được và trả về giá trị datetime trong GMT và chuyển đổi sang múi giờ địa phương được thực hiện ở phía khách hàng. – OrPo

+0

Bạn có thể gửi yêu cầu không? Tôi tự hỏi bạn đã sử dụng định dạng nào bên trong JSON? Bạn đang sử dụng một chuỗi thời gian nhận biết chuỗi ISO 8601? – codingjoe

Trả lời

31

tôi đã cùng một vấn đề và giải quyết nó bằng cách thêm loại mới của lĩnh vực:

class DateTimeTzAwareField(serializers.DateTimeField): 

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

và bây giờ bạn có thể sử dụng nó trong ModelSerializer:

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

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

Một sửa chữa nhỏ - nếu trường này cũng có thể là rỗng, yêu cầu kiểm tra đơn giản, ví dụ: 'if value: value = timezone.localtime (value)' – Ophir

+4

New Django-Rest-Framework, sử dụng 'to_representation' thay thế của 'to_native' – db0

+0

Làm việc như một sự quyến rũ, cảm ơn! –

14

Câu trả lời bởi @yakxxx có vẻ là giải pháp tốt nhất. Tôi gửi bài nó một lần nữa sau khi cập nhật nó để làm việc với các phiên bản mới hơn của restframework

bên trong thư mục của tôi (common/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) 

Bên trong ứng dụng của tôi

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

Không cần kiểm tra nếu giá trị là Không có đề xuất của Ophir. Rõ ràng nếu giá trị không phải là phương pháp này sẽ không bao giờ được gọi là – Ramast

+0

Tôi có thể đặt 'DEFAULT_DATETIME_PARSER = 'common.serializers không. DateTimeFieldWihTZ 'để thay đổi tất cả DatetimeField thành DateTimeFieldWihTZ? – kxxoling

+1

Tôi không biết bất kỳ cài đặt khung còn lại nào có tên đó – Ramast

Các vấn đề liên quan