Skip to main content
 首页 » 编程设计

python之接受 Django 形式的日期时间同种格式

2024年10月25日38mate10pro

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

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 的 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): 
            """ stackoverflow won't let me save just an indent! """ 
            return parse_datetime(force_str(value))