DjangoRestFramework ModelSerializer DateTimeField只能在创建对象时转换为当前时区 [英] DjangoRestFramework ModelSerializer DateTimeField only converting to current timezone at object creation

查看:2373
本文介绍了DjangoRestFramework ModelSerializer DateTimeField只能在创建对象时转换为当前时区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This has now been recognized as a bug and it looks like a fix is in progress: https://github.com/tomchristie/django-rest-framework/issues/3732#issuecomment-267635612

我有一个Django项目,我期望用户处于某个时区。我的设置中有 TIME_ZONE ='亚洲/加尔各答' USE_TZ = True

I have a Django project where I expect the user to be in a certain timezone. I have TIME_ZONE = 'Asia/Kolkata' and USE_TZ = True in my settings.

我有一个包含datetime字段的模型。当我第一次创建对象时,modelserializer会给出数据时间,后跟 +5:30 。令人讨厌的是,datetimes与 auto_now_add = True 给出UTC数据时间,后跟 Z 。我通过使该字段的默认值为当前时间被调用来修复此问题。

I have a model that includes a datetimefield. When I first create the object, the modelserializer gives datetimes with a trailing +5:30. Annoyingly, datetimes with auto_now_add=True give UTC datetimes with a trailing Z. I fixed this by making the field's default a callable for the current time.

如果我在任何时候重新序列化对象,则所有数据时间都以UTC为单位,尾随 Z 。从Django文档中,我希望序列化程序使用当前的时区,默认时区为 TIME_ZONE ='Asia / Kolkata'设置的时区。我已经使用 get_current_timezone_name()检查当前时区,它是'亚洲/加尔各答'。我甚至试图在我看来使用 activate('亚洲/加尔各答'),但是UTC仍然被返回。

If I serialize the object again at any point, all datetimes are in UTC with a trailing Z. From the Django documentation, I would expect the serializer to use the current timezone, which defaults to the default timezone set by TIME_ZONE = 'Asia/Kolkata'. I have checked the current timezone in my view with get_current_timezone_name() and it is 'Asia/Kolkata'. I have even tried using activate('Asia/Kolkata') in my view, but times are still being returned in UTC.

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

Note that all the times are correct (the UTC times are 5:30 hours earlier), its just that I would expect for the times to be converted. All datetimes are stored in the DB as UTC times as expected.

我是否缺少某些东西,或者是Django Rest Framework序列化程序中的错误?

Am I missing something or is this a bug with the Django Rest Framework serializers?

推荐答案

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

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

Signature: DateTimeField(format=None, input_formats=None)

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

format - A string representing the output format. If not specified, this defaults to the same value as the DATETIME_FORMAT settings key, which will be 'iso-8601' unless set. Setting to a format string indicates that to_representation return values should be coerced to string output. Format strings are described below. Setting this value to None indicates that Python datetime objects should be returned by to_representation. In this case the datetime encoding will be determined by the renderer.

当格​​式为datetime对象使用无值时,对象将由to_representation返回,最终的输出表示将由渲染器类确定。

When a value of None is used for the format datetime objects will be returned by to_representation and the final output representation will determined by the renderer class.

在JSON的情况下,这意味着默认的datetime表示使用ECMA 262日期时间字符串规范。这是ISO 8601的一个子集,它使用毫秒精度,并且包括UTC时区的Z后缀,例如:2013-01-29T12:34:56.123Z。

In the case of JSON this means the default datetime representation uses the ECMA 262 date time string specification. This is a subset of ISO 8601 which uses millisecond precision, and includes the 'Z' suffix for the UTC timezone, for example: 2013-01-29T12:34:56.123Z.

所以获取datetime对象的UTC(Z)表示实际上是默认行为。

So getting the UTC (Z) representation of your datetime object is in fact default behaviour.

当您创建更新通过Djangorest的模型实例,序列化程序将被调用与数据 kwarg,如果您使用不会发生列表或详细视图。

When you create or update a model instance through Djangorest, the serializer will be called with the data kwarg, which doesn't happen if you use the list or detail view.

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

In both cases, your view will return serializer.data. In case of a create/update operation, this will be a representation of serializer.validated_data, while in case of a list/detail operation it'll be a direct representation of the instance.

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

In both cases, the representation is achieved by calling field.to_representation with the default kwarg format=None, which will make the field return the plain string value.

魔术发生在这里


  • 创建/更新:验证返回时区感知对象,其中包含您的标准时区。它通过调用其 isoformat()方法转换为字符串,并按原样返回。

  • 列表/检索:django ORM将时间戳记存储为UTC。它通过调用其 isoformat()方法而转换为字符串,但DRF将 +00:00 替换为 Z (见上面的链接)。

  • create/update: The validation returns a timezone aware object, which includes your standard timezone. It is converted to string by calling its isoformat() method, and returned as-is.
  • list/retrieve: The django ORM stores the timestamp as UTC. It is converted to string by calling its isoformat() method, but DRF replaces +00:00 with Z (see the link above).

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

So to get the desired output with timezone offset, you could pass format=None or a custom strftime string to the DateTimeField in your serializer. However, you will always get the UTC time with +00:00, because that's what the data is (fortunately) stored as.

如果要实际的偏移量为'亚洲/加尔各答',您可能需要定义自己的 DateTimeField

If you want the actual offset to 'Asia/Kolkata', you will probably have to define your own 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) 

这篇关于DjangoRestFramework ModelSerializer DateTimeField只能在创建对象时转换为当前时区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆