我的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。
答案 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)