如何让 Django Rest Framework DateTimeField 需要时区信息?
How do I get a Django Rest Framework DateTimeField to require timezone information?
我有一个带有 DateTimeField 的 Django Rest Framework 序列化程序。默认情况下,它将使用 iso-8601 格式反序列化 date/time 值。但是,iso-8601 不需要时区偏移量。我需要用户始终提供一些时区偏移信息(或者更好地说,再次验证 rfc 3339,iso-8601 的一个子集)。
该字段允许您设置 input_formats 的自定义列表,但由于 Python 无法正确解析 rfc 3339 格式的日期(即小时和分钟部分之间带有冒号的偏移量不受支持)我卡住了。
Django Rest Framework 中的 DateTimeField 完全能够解析 rfc 3339 日期时间值,这要归功于它使用了 django.utils.dateparse.parse_datetime
(它有点宽松,但没关系)。
parse_datetime
returns 可识别时区的日期时间实例(具有固定偏移量的 tzinfo zet)或简单的日期时间实例(无 tzinfo)。
Django Rest Framework 的 DateTimeField 将任何给定值转换为感知日期时间值,如果设置了 settings.USE_TZ
或者字段被赋予了 default_timezone
参数的值,否则任何值都被设为天真。
DateTimeField的enforce_timezone
方法负责取值aware/naive.
知道这一点,如果解析的日期时间值是天真的,则可以通过覆盖 enforce_timezone
并引发 ValidationError
来强制解析的值必须是时区感知的:
from django.utils import timezone
class DateTimeFieldWithOffset(serializers.DateTimeField):
default_error_messages = {
'naive': 'Datetime value is missing a timezone offset.'
}
def enforce_timezone(self, value):
if timezone.is_naive(value):
self.fail('naive')
return super().enforce_timezone(value)
我有一个带有 DateTimeField 的 Django Rest Framework 序列化程序。默认情况下,它将使用 iso-8601 格式反序列化 date/time 值。但是,iso-8601 不需要时区偏移量。我需要用户始终提供一些时区偏移信息(或者更好地说,再次验证 rfc 3339,iso-8601 的一个子集)。
该字段允许您设置 input_formats 的自定义列表,但由于 Python 无法正确解析 rfc 3339 格式的日期(即小时和分钟部分之间带有冒号的偏移量不受支持)我卡住了。
Django Rest Framework 中的 DateTimeField 完全能够解析 rfc 3339 日期时间值,这要归功于它使用了 django.utils.dateparse.parse_datetime
(它有点宽松,但没关系)。
parse_datetime
returns 可识别时区的日期时间实例(具有固定偏移量的 tzinfo zet)或简单的日期时间实例(无 tzinfo)。
Django Rest Framework 的 DateTimeField 将任何给定值转换为感知日期时间值,如果设置了 settings.USE_TZ
或者字段被赋予了 default_timezone
参数的值,否则任何值都被设为天真。
DateTimeField的enforce_timezone
方法负责取值aware/naive.
知道这一点,如果解析的日期时间值是天真的,则可以通过覆盖 enforce_timezone
并引发 ValidationError
来强制解析的值必须是时区感知的:
from django.utils import timezone
class DateTimeFieldWithOffset(serializers.DateTimeField):
default_error_messages = {
'naive': 'Datetime value is missing a timezone offset.'
}
def enforce_timezone(self, value):
if timezone.is_naive(value):
self.fail('naive')
return super().enforce_timezone(value)