当前位置:  开发笔记 > 编程语言 > 正文

DjangoRestFramework ModelSerializer DateTimeField仅在创建对象时转换为当前时区

如何解决《DjangoRestFrameworkModelSerializerDateTimeField仅在创建对象时转换为当前时区》经验,为你挑选了1个好方法。

编辑:这已经被认为是一个错误,它看起来像一个修复正在进行中:https://github.com/tomchristie/django-rest-framework/issues/3732#issuecomment-267635612

我有一个Django项目,我希望用户在某个时区.我TIME_ZONE = 'Asia/Kolkata'USE_TZ = True我的设置.

我有一个包含datetimefield的模型.当我第一次创建对象时,modelserializer给出带尾随的日期时间+5:30.令人讨厌的是,日期时间auto_now_add=True为UTC日期时间提供尾随Z.我通过使字段的默认值为当前时间的可调用来修复此问题.

如果我在任何时候再次序列化对象,则所有日期时间都是UTC,并带有尾随Z.从Django文档中,我希望序列化程序使用当前时区,默认为默认时区设置TIME_ZONE = 'Asia/Kolkata'.我已经在我的视图中检查了当前时区get_current_timezone_name(),它是'Asia/Kolkata'.我甚至尝试过activate('Asia/Kolkata')在我的视图中使用,但时间仍在UTC中返回.

请注意,所有时间都是正确的(UTC时间早于5:30),这正是我期望转换的时间.所有日期时间都按照预期的UTC时间存储在数据库中.

我错过了什么,或者这是Django Rest Framework序列化程序的错误?



1> Geotob..:

看看这里的文档:http://www.django-rest-framework.org/api-guide/fields/#datetimefield

签名:DateTimeField(format = None,input_formats = None)

format - 表示输出格式的字符串.如果未指定,则默认为与DATETIME_FORMAT设置键相同的值,除非设置,否则将为"iso-8601".设置为格式字符串表示to_representation返回值应强制转换为字符串输出.格式字符串如下所述.将此值设置为None表示to_representation应返回Python datetime对象.在这种情况下,日期时间编码将由渲染器确定.

如果将值设置为None,则datetime对象将由to_representation返回,最终输出表示将由renderer类确定.

对于JSON,这意味着默认的日期时间表示使用ECMA 262日期时间字符串规范.这是ISO 8601的子集,使用毫秒精度,并包括UTC时区的"Z"后缀,例如:2013-01-29T12:34:56.123Z.

因此,获取datetime对象的UTC(Z)表示实际上是默认行为.

当您通过Djangorest 创建更新模型实例时,将使用datakwarg 调用序列化程序,如果您使用列表或详细信息视图,则不会发生这种情况.

在这两种情况下,您的视图都将返回serializer.data.在创建/更新操作的情况下,这将是表示serializer.validated_data,而在列表/细节操作的情况下,它将是实例的直接表示.

在这两种情况下,通过field.to_representation使用默认的kwarg 调用来实现表示format=None,这将使字段返回纯字符串值.

魔术发生在这里:

create/update:验证返回一个时区感知对象,其中包括您的标准时区.它通过调用其isoformat()方法转换为字符串,并按原样返回.

list/retrieve:django ORM将时间戳存储为UTC.它通过调用isoformat()方法转换为字符串,但DRF替换+00:00Z(参见上面的链接).

因此,要获得具有时区偏移量的所需输出,您可以将format=None自定义strftime字符串传递给序列化程序中的DateTimeField.但是,您将始终获得UTC时间+00:00,因为这是(幸运的是)存储的数据.

如果你想要实际的偏移量'Asia/Kolkata',你可能需要定义自己的DateTimeField:

from django.utils import timezone
class CustomDateTimeField(serializers.DateTimeField):
    def to_representation(self, value):
        tz = timezone.get_default_timezone()
        # timezone.localtime() defaults to the current tz, you only
        # need the `tz` arg if the current tz != default tz
        value = timezone.localtime(value, timezone=tz)
        # py3 notation below, for py2 do:
        # return super(CustomDateTimeField, self).to_representation(value)
        return super().to_representation(value) 

推荐阅读
小白也坚强_177
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有