如何从Django Rest Framework序列化程序返回不同时区的DateTime

时间:2018-12-12 19:03:01

标签: python django datetime django-rest-framework timezone

在Django Rest Framework中使用任意时区返回某些Django模型的DateTimeField的pythonic方法是什么?

此刻,我的视图以UTC返回DateTime,因为据我所知,Django将时区感知的日期时间存储为UTC时区中的日期时间。

型号:

class TimezoneMixin(models.Model):
    TIMEZONES = [(i, i) for i in country_timezones['ru']]

    timezone = models.CharField(choices=TIMEZONES, ...)

    class Meta:
        abstract = True

    def get_timezone(self):
        if self.timezone:
            return timezone(self.timezone)
        return get_current_timezone()


class Organization(TimezoneMixin, models.Model):
    ...

class Event(models.Model):
    organization = models.ForeignKey(Organization, ...)
    date_created = models.DateTimeField(auto_now_add=True, ...)
    ...

序列化器:

class EventSerializer(serializers.ModelSerializer):

    class Meta:
        model = Event
        fields = ('organization', 'date_created', ...)

在ViewSet中,我如下填充数据

organization_id = ...  # Some logic to get required organization_id

data = {
    'date_created': timezone.now(), # django.utils.timezone
    'organization': organization_id,
    ...
}

serializer = EventSerializer(data=data)
if serializer.is_valid():
    serializer.save()
    response_data = serializer.data.copy()
    # Some logic to rename one of the keys in response data
    ...
    return Response(response_data, ...)  # rest_framework.response.Response

即使我将timezone.now()替换为timezone.now().astimezone(organization.get_timezone())之类的内容,我仍然会收到UTC DateTime作为响应。

我是否纠正从date_created解析response_data字符串,从中创建DateTime对象,转换为不同的时区并在视图末尾再次格式化为字符串不是一个好主意?还有什么其他方法?

3 个答案:

答案 0 :(得分:1)

您需要localtime()才能获取当前时区的时间,因为now()将始终以UTC返回时间,而与TIME_ZONE的值无关。

您可以将任意时区传递给本地时间:

localtime(timezone='SOMETHING')

答案 1 :(得分:0)

我能够在任意时区获得时间戳,而无需解析datetime字符串,因为serializer可以访问保存的instance。所以下面是我的解决方法

response_data = serializer.data.copy()
# Some logic to rename one of the keys in response data
...
event_date_created_utc = serializer.instance.date_created
# Basically calls get_timezone on Organization instance and returns the result
organization_timezone = get_timezone_by_organization_id(organization_id)
response_data['date_created'] = timezone.localtime(event_date_created_utc,
                                                   timezone=organization_timezone).isoformat()
return Response(response_data, ...)  # rest_framework.response.Response

感谢Edgar R.Mondragón提到localtime()及其用法。

答案 2 :(得分:0)

序列化器使用默认的TIME_ZONE,您可以在settings.py文件中设置

如果要为一个字段设置“时区”。

import pytz
class WeatherReportSerializer(serializers.ModelSerializer):
    DatetimeValue = serializers.DateTimeField(default_timezone=pytz.timezone('Asia/Kolkata'))
    
    class Meta:
        model = ...
        fields = [..., ..., ...]