在DRF中使用与models.DateTimeField相同的日期/时间格式

时间:2015-06-02 09:04:25

标签: javascript python django django-rest-framework

我的Build模型带有start_time字段,其类型为models.DateTimeField。另一方面,我有一个BuildSerializer类,其中包含此start_time字段。现在,当我在模板中打印时间戳时,我得到如下结果:

{{ build.start_time|format:'DATETIME_FORMAT' }}
我的模板中的

将变为:

April 24, 2015, 8:03 a.m.

但是,序列化器输出不同的值:

2015-04-24T08:03:39.336922Z

这很好,因为它是标准的JSON日期表示。但是,我想根据用户的语言环境显示它,就像Django在使用上面的模板片段时所做的那样。

我尝试使用

timestamp = serializers.DateTimeField(format=settings.DATETIME_FORMAT)

但是DRF使用不同的方式来格式化日期输出,所以这只会输出:

"N j, Y, P"

表示默认的en-us语言区域。

有没有办法像Django那样格式化日期?我对python或JavaScript解决方案感兴趣,因为我总是在JS函数(AJAX回调)中处理JSON。

3 个答案:

答案 0 :(得分:1)

高度建议将您的日期格式设置为ISO 8601(这是默认设置),因为它是一致且标准化的日期格式,因此您不需要&#39 ; t需要过多担心在任何地方手动解析日期。大多数语言都可以解析ISO 8601日期,而那些默认情况下无法使用的库通常都有可以为您完成的库。

  

有没有办法像Django那样格式化日期?

Django REST框架默认只支持使用单个格式化程序格式化与日期相关的字段,默认情况下为ISO 8601。这是为了保持一致性,因此客户端可以发送OPTIONS请求并直接从那里解析日期格式,并依赖于永不更改的日期格式。

可以通过在模型上拥有属性或覆盖返回值的SerializerMethodField来覆盖此行为,以便在需要时调用Django的日期格式化实用程序在后端本地化值。或者,您可以覆盖默认的DateTimeField to_native方法并在那里进行格式化,这样您就可以拥有一个可以在序列化程序中使用的字段,以便本地化保持一致。

  

我对python或JavaScript解决方案感兴趣,因为我总是在JS函数(AJAX回调)中处理JSON。

我们用于解析ISO 8601次的JavaScript解决方案是Moment.js。虽然某些浏览器可以解析ISO 8601次,但并非所有浏览器都可以将它们传递给Moment更容易,因此可以在JavaScript Date objects中进行转换。

// parse the incoming date/time string
var start = moment(response.start_time, moment.ISO_8601);

moment的第一个参数是要解析的字符串,第二个参数是要解析的格式。 moment.ISO_8601是一个特殊的钩子,它可以自动将其解析为有效的ISO 8601时间,这就是我们使用它的原因。

从那里,您可以使用浏览器的日期本地化向用户显示该时间的本地化版本。日期对象提供toLocaleString()toLocaleDateString()toLocaleTimeString()方法,可用于格式化日期(或整个事物)的不同部分用户期望的方式。

在Chrome上进行本地测试(在Ubuntu,en-US上)我获得了以下方法的输出

> (new Date()).toLocaleString()
< "6/2/2015, 7:23:03 PM"
> (new Date()).toLocaleDateString()
< "6/2/2015"
> (new Date()).toLocaleTimeString()
< "7:23:12 PM"

我为此浏览器配置了我的日期设置。这还有额外的好处,即始终使用系统的当前时区,因此您不必担心本地化的这一部分 - 它会自动处理。

答案 1 :(得分:0)

我已经很快找到了解决方案,虽然我觉得它有点难看:

from django.utils import formats

class BuildSerializer(serializers.ModelSerializer):
    timestamp_django = serializers.SerializerMethodField()

    def get_timestamp_django(self, obj):
       return formats.date_format(obj.timestamp, 'DATETIME_FORMAT')

    class Meta:
        model = Build
        fields = ('timestamp', 'timestamp_django', …)

通过这种方式,我可以充分利用这两个世界,因为我仍然可以将JSON日期用于其他目的(例如过滤或排序)。

答案 2 :(得分:0)

以下是我的解决方案,基于Kevin Brown's answer

from django.utils import formats
from rest_framework import serializers
from rest_framework.settings import api_settings

class DateTimeField(serializers.DateTimeField):
    """DateTime field whichs supports Django's format definitions."""

    def to_representation(self, obj):
        if api_settings.DATETIME_FORMAT in formats.FORMAT_SETTINGS:
            return formats.date_format(obj, api_settings.DATETIME_FORMAT)
        return super().to_representation(obj)


class DateField(serializers.DateField):
    """Date field whichs supports Django's format definitions."""

    def to_representation(self, obj):
        if api_settings.DATE_FORMAT in formats.FORMAT_SETTINGS:
            return formats.date_format(obj, api_settings.DATE_FORMAT)
        return super().to_representation(obj)


class TimeField(serializers.TimeField):
    """Time field whichs supports Django's format definitions."""

    def to_representation(self, obj):
        if api_settings.TIME_FORMAT in formats.FORMAT_SETTINGS:
            return formats.date_format(obj, api_settings.TIME_FORMAT)
        return super().to_representation(obj)