代码之家  ›  专栏  ›  技术社区  ›  Halvor Holsten Strand mtorres

强制严格的字段。日期格式与棉花糖反序列化

  •  0
  • Halvor Holsten Strand mtorres  · 技术社区  · 6 年前

    我正在为一个Flask项目使用marshmallow2.15.3,希望强制执行严格的日期和日期时间格式。对于strict,我的意思是我只想接受与下面格式相同的字符串。我所经历的是在处理日期和日期时间上的一些不同。格式:

    DATE_FORMAT = '%Y-%m-%d'
    DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S'
    

    例如,使用DateTime可以执行以下操作:

    dt = fields.DateTime(format=DATETIME_FORMAT)
    dt.deserialize('2018-01-01')  # fails, as desired
    dt.deserialize('2018-01-01T05:06:08.012312+02:00')  # fails, as desired
    dt.deserialize('2018-01-01T05:06:08')  # works, as desired and according to format
    

    d = fields.Date() # does not accept format argument
    d.deserialize('2018-01')  # fails, as desired
    d.deserialize('2018-01-01T05:06:08.012312+02:00')  # works, NOT as desired
    d.deserialize('2018-01-01')  # works, as desired and according to format
    

    虽然DateTime不允许额外的信息,但Date允许。据我所知没有 format

    1 回复  |  直到 6 年前
        1
  •  3
  •   Halvor Holsten Strand mtorres    6 年前

    对于未来证明代码,我发现 Date 棉花糖3.0.0b17中的类现在是 DateTime 而不是 Field ,使其继承 format relevant commit ).

    对于版本2.15.3和2.X.X,我找不到任何内置函数。一个解决办法是修补 fields.Date 班级。经过修改后,它看起来是这样的:

    class Date(Field):
        """ISO8601-formatted date string.
    
        :param kwargs: The same keyword arguments that :class:`Field` receives.
        """
        default_error_messages = {
            'invalid': 'Not a valid date.',
            'format': '"{input}" cannot be formatted as a date.',
        }
    
        def __init__(self, format=None, **kwargs):
            super(Date, self).__init__(**kwargs)
            self.dateformat = format
    
        def _serialize(self, value, attr, obj):
            if value is None:
                return None
            try:
                return value.isoformat()
            except AttributeError:
                self.fail('format', input=value)
            return value
    
        def _deserialize(self, value, attr, data):
            """Deserialize an ISO8601-formatted date string to a
            :class:`datetime.date` object.
            """
            if not value:  # falsy values are invalid
                self.fail('invalid')
            elif self.dateformat:
                try:
                    return dt.datetime.strptime(value, self.dateformat).date()
                except (TypeError, AttributeError, ValueError):
                    raise self.fail('invalid')
            try:
                return utils.from_iso_date(value)
            except (AttributeError, TypeError, ValueError):
                self.fail('invalid')
    

    这里的修改是 __init__ 定义和定义 _deserialize elif self.dateformat -已添加子句。这允许我使用提交的格式反序列化,例如:

    d = fields.Date('%Y-%m-%d') # now accepts a format
    d.deserialize('2018-01-01T05:06:08.012312+02:00')  # fails, as desired