Обеспечить строгие поля. Формат даты с десериализацией Зефир
Я использую Marshmallow 2.15.3 для проекта Flask и хочу использовать строгие форматы Date и DateTime. Под строгим подразумевается, что я хочу принимать только строки, идентичные форматам ниже. То, что я испытываю, это некоторая разница в обработке Date и DateTime. Форматы:
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 ответ
Для будущего кода я считаю, что Date
класс в Зефир 3.0.0b17 теперь подкласс DateTime
вместо Field
заставляя его наследовать format
kwarg ( соответствующий коммит).
Для версий 2.15.3 и (2.XX в целом) я не могу найти встроенную функцию для этого. Обходной путь должен обезьяна исправить 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