I'm building an app that would serve people located in different places arround the world.
I'm using Django-Rest-Framwork for the communication between the clients and the server.
All DateTime values are saved to the DB as UTC (I have USE_TZ = True
and TIME_ZONE = 'Greenwich'
in settings.py).
I will be getting from the user his/her local timezone.
To test DRF for timezone awareness I wrote this middleware with fixed timezone:
import pytz
from django.utils import timezone
class TimezoneMiddleware(object):
def process_request(self, request):
timezone.activate(pytz.timezone("Asia/Jerusalem"))
The problem is:
I have a case in which I'm getting from the user "start_time" and "end_time" fields containting datetimes in the user's LOCAL timezone which gets through the UnicodeJSONRenderer
to a ModelSerializer
and then saved to the DB. However, they are saved as if they were in UTC.
At this point I would expect the serializer (or parser) to treat the datetime input from the user as datetime that needs to be converted from "Asia/Jerusalem" to UTC before saving to the DB since I performed timezone.activate(pytz.timezone("Asia/Jerusalem"))
.
The same goes when the data is parsed back in the response through JSONParser
.
While expecting DateTime fields in the returned JSON to be in the timezone activated in the middleware, they are returned as UTC.
How can I easily achieve that in DRF?
I had the same problem and solved it by adding new type of field:
and now you can use it in
ModelSerializer
:The answer by @yakxxx seems to be the best solution. I am posting it again after updating it to work with newer versions of restframework
inside my directory (common/serializers.py)
Inside my application
Since Django REST Framework v3.8.0(released in May, 2018), you don't need a custom DateTimeField any more.
In previous versions, Django REST Framework only convert native datetime to timezone aware datetime when parsing the date(
DateTimeField.to_internal_value()
), but do not convert when rendering the datatime field(DateTimeField.to_representation()
). This is fixed in DRF v3.8.0.You may need to change the following settings:
USE_TZ
must be TrueTIME_ZONE
to specify a default timezoneREST_FRAMEWORK.DATETIME_FORMAT
to the format that fits your frontend code.