编辑:现在已经认识到这是一个错误,看起来修复工作正在进行中: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序列化程序的错误?
答案 0 :(得分:8)
请查看此处的文档: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返回,最终输出表示将由渲染器类确定。
对于JSON,这意味着默认日期时间表示使用ECMA 262日期时间字符串规范。这是ISO 8601的一个子集,它使用毫秒精度,包括' Z' UTC时区的后缀,例如:2013-01-29T12:34:56.123Z。
因此,获取datetime对象的UTC(Z)表示实际上是默认行为。
当您通过Djangorest 创建或更新模型实例时,将使用data
kwarg调用序列化程序,如果没有serializer.data
kwarg你使用列表或详细信息视图。
在这两种情况下,您的视图都会返回serializer.validated_data
。如果是创建/更新操作,这将是field.to_representation
的表示,而在列表/详细信息操作的情况下,它将是直接表示实例。
在这两种情况下,通过使用默认的kwarg format=None
调用isoformat()
来实现表示,这将使字段返回纯字符串值。
魔术发生here:
isoformat()
方法转换为字符串,并按原样返回。+00:00
方法转换为字符串,但DRF用Z
替换format=None
(请参阅上面的链接)。因此,要获得具有时区偏移量的所需输出,可以将+00:00
或自定义strftime字符串传递给序列化程序中的DateTimeField。但是,您将始终使用'Asia/Kolkata'
获取UTC时间,因为这样的数据(幸运的是)存储为。
如果您希望实际偏移量为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)
:
server:
port: ${PORT:8989}
management:
port: 8990
---
spring:
profiles: cloud
management:
port: -1