Могут ли webargs / Marshmallow в Python изменить поле, а не просто проверить его?
Я использую Flask с flask-restful и webargs (который использует Marshmallow в качестве бэкэнда). В настоящее время я могу тянуть в поля, которые я хочу с этим:
class AddGroup(Resource):
args = {
'name': fields.Str(missing=None),
'phone': fields.Str(missing=None),
}
@use_args(args)
def get(self, args):
name = args['name'].strip()
# ... some GET-related code ...
@use_args(args)
def post(self, args):
name = args['name'].strip()
# ... some POST-related code ...
Все идет нормально. Но то, что я действительно хотел бы сделать, это убедиться, что args['name']
входит в различные методы ("post", "get" и т. д.) с уже удаленными пробелами, поэтому мне не нужно каждый раз обрабатывать каждую переменную вручную. (удаление пробелов является лишь примером - это может быть другое простое или сложное преобразование)
Есть ли способ (либо путем переопределения поля String, определения моего собственного поля, либо как угодно), который позволит args
быть предварительно обработанным, прежде чем они прибудут в методы класса?
2 ответа
Поскольку webargs
используют marshmallow
чтобы сделать схему, вы можете использовать pre_load
или же post_load
, Вот пример с "slugify" строкой в документах о зефире:
from marshmallow import Schema, fields, pre_load
class UserSchema(Schema):
name = fields.Str()
slug = fields.Str()
@pre_load
def slugify_name(self, in_data):
in_data['slug'] = in_data['slug'].lower().strip().replace(' ', '-')
return in_data
schema = UserSchema()
result = schema.load({'name': 'Steve', 'slug': 'Steve Loria '})
result['slug'] # => 'steve-loria'
Вы можете увидеть подробные документы здесь: https://marshmallow.readthedocs.io/en/latest/extending.html
Вы можете использовать следующий класс настраиваемого поля (в качестве композиции):
from marshmallow import fields
class Trim(fields.Field):
def __init__(self, inner, *args, **kwargs):
self.inner = inner
super().__init__(*args, **kwargs)
def _bind_to_schema(self, field_name, parent):
super()._bind_to_schema(field_name, parent)
self.inner._bind_to_schema(field_name, parent)
def _deserialize(self, value, *args, **kwargs):
value = value.strip()
return self.inner._deserialize(value, *args, **kwargs)
def _serialize(self, *args, **kwargs):
return self.inner._serialize(*args, **kwargs)
Пример использования:
from marshmallow import Schema, fields
class SomeSchema(Schema):
name = Trim(fields.String(), validate=validate.Length(max=100))
email = Trim(fields.Email(), required=True)
Идея отсюда