接受Django形式的datetime isoformat

时间:2015-04-10 07:56:20

标签: python django validation datetime timezone

在Django之上构建了一个API服务器。模型Author具有DateTimeField,序列化为iso格式的字符串,例如2015-04-10T07:28:45.571039+00:00

class Author(models.Model):
    created = models.DateTimeField()

客户端在Javascript中实现。它使用给定的datetime字段构建模型,所以为了更新模型,我想以相同的格式使用字段。

要在服务器端处理请求,有一个模型表单

class AuthorForm(forms.ModelForm):
    class Meta:
        model = Author

POST / PUT请求处理程序引发异常:“输入有效的日期/时间。”。允许DATETIME_INPUT_FORMATS的原因。内部冒号无法接受时区信息。

鉴于我不想删除时区支持(USE_TZ)并希望接受带有时区信息的数据,实现服务器端的方法是什么?我目前有两个解决方案:1)完全排除字段2)在表单清除方法中使用CharField函数形式使用dateutil.parser.parse。 你有什么建议可以解决吗?

3 个答案:

答案 0 :(得分:1)

Python(3.7之前的版本)无法使用+00:00处理ISO8601字符串。具体而言,冒号就是问题(参见:https://bugs.python.org/issue15873https://bugs.python.org/msg169952)。但是,Django通过django.utils.dateparse.parse_datetime提供解决方案(参见:https://stackoverflow.com/a/30449246/5043802

要解决此问题,您可以推出自己的使用parse_datetime的DateTimeField。

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):
    return parse_datetime(force_str(value))

答案 1 :(得分:0)

您的存储不太可能接受时区感知日期时间,您的django应用程序是否设置了时区?来自文档:

  

当启用对时区的支持时,Django会存储日期时间   数据库中的UTC信息使用时区感知日期时间   内部对象,并将它们转换为最终用户的时区   模板和表格。

如果你没有使用postgresql:

  

其他后端存储没有时区信息的日期时间。如果你   从USE_TZ = False切换到USE_TZ = True,你必须转换你的   从当地时间到UTC的数据 - 如果您的本地时间不确定   时间有DST。

基本上,只是在settings.py

中设置USE_TZ并不是完全没有完成的

答案 2 :(得分:0)

我使用@elnygren代码,并且遇到一个错误,该错误的形式是不需要ISODateTimeField字段,它会一直尝试进行验证,我通过以下方式进行了修复:

session()->push()