Django之上有一个API服务器构建。模型 Author
具有序列化为 iso 格式字符串(如 2015-04-10T07:28:45.571039+00:00
(的DateTimeField
。
class Author(models.Model):
created = models.DateTimeField()
客户端是用Javascript实现的。它使用给定的日期时间字段构建模型,因此要更新模型,我想使用相同的格式字段。
为了在服务器端处理请求,有一个模型表单
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
POST/PUT 请求处理程序引发异常:"输入有效的日期/时间。原因DATETIME_INPUT_FORMATS允许。无法接受包含冒号的时区信息。
鉴于我不想删除时区支持(USE_TZ(并希望接受带有时区信息的数据,实现服务器端的方法是什么?我目前有两种解决方案:1(全部排除字段2(在表单中使用CharField
dateutil.parser.parse
并在表单清理方法中使用函数。你有什么建议如何处理吗?
Python(3.7 之前(无法处理 +00:00 的ISO8601字符串。具体来说,冒号是问题所在(见:https://bugs.python.org/issue15873,https://bugs.python.org/msg169952(。然而,Django 确实通过 django.utils.dateparse.parse_datetime
提供了一个解决方案(参见:https://stackoverflow.com/a/30449246/5043802(
要解决此问题,您可以推出自己的日期时间字段,改用parse_datetime
。
https://gist.github.com/elnygren/da7a1b7496a598f95bc8d8277f420b2d
from django import forms
from django.utils.dateparse import parse_datetime
from django.utils.encoding import force_str
from django.forms.widgets import DateTimeInput
from django.utils.translation import gettext_lazy as _, ngettext_lazy
class ISODateTimeField(forms.Field):
"""DateTimeField that uses django.utils.dateparse.parse_datetime.
More precisely, this DateTimeField accepts ISO 8601 datetime strings
that specify timezone with +00:00 syntax.
https://en.wikipedia.org/wiki/ISO_8601
https://code.djangoproject.com/ticket/11385
https://bugs.python.org/issue15873
https://bugs.python.org/msg169952
"""
widget = DateTimeInput
default_error_messages = {
'invalid': _('Enter a valid date/time.'),
}
def to_python(self, value):
value = value.strip()
try:
return self.strptime(value, format)
except (ValueError, TypeError):
raise forms.ValidationError(self.error_messages['invalid'], code='invalid')
def strptime(self, value, format):
""" stackoverflow won't let me save just an indent! """
return parse_datetime(force_str(value))
您的存储不太可能接受时区感知日期时间,您的 Django 应用程序是否针对时区进行了设置? 从文档中:
启用时区支持后,Django 会存储日期时间 数据库中的 UTC 信息,使用时区感知日期时间 对象在内部,并将它们转换为最终用户的时区 模板和表单。
另外,如果您不使用PostgreSQL:
其他后端存储没有时区信息的日期时间。如果你 从 USE_TZ = False 切换到 USE_TZ = True,您必须转换您的 从本地时间到 UTC 的数据 - 如果您的本地时间,则不确定 时间有夏令时。
基本上,它并没有完全为您完成,只是在 settings.py 中设置USE_TZ
我使用@elnygren代码,并且我有一个表单错误,即不需要ISODateTimeField字段,它一直尝试验证,我以这种方式修复:
def to_python(self, value):
if value in self.empty_values:
return None
value = value.strip()
for _format in self.input_formats:
try:
return self.strptime(value, _format)
except (ValueError, TypeError):
continue
raise forms.ValidationError(self.error_messages["invalid"], code="invalid")