有三种方式创建自定义的field。
创建Field类的子类
创建继承自marshmallow.fields.Field
类的子类并实现_serialize
和/或_deserialize
方法:
from marshmallow import fields, Schema
class Titlecased(fields.Field):
def _serialize(self, value, attr, obj):
if value is None:
return ''
return value.title()
class UserSchema(Schema):
name = fields.String()
email = fields.String()
created_at = fields.DateTime()
titlename = TitleCased(attribute="name")
Method Fields
fields.Method
将序列化schema中某个方法的返回值,该方法必须接收一个要进行序列化的对象的参数obj
:
class UserSchema(Schema):
name = fields.String()
email = fields.String()
created_at = fields.DateTime()
since_created = fields.Method("get_days_since_created")
def get_days_since_created(self, obj):
return dt.datetime.now().day - obj.created_at.day
Function Fields
fields.Function
将序列化传递给它的函数的返回值,也接收一个obj
参数:
class UserSchema(Schema):
name = fields.String()
email = fields.String()
created_at = fields.DateTime()
uppername = fields.Function(lambda obj: obj.name.upper())
Method和Function的反序列化
fields.Method
和fields.Function
都接收一个可选的deserialize
参数,该参数定义了如何反序列化字段:
class UserSchema(Schema):
# Method接收字符串类型的方法名, Function接收callable对象
balance = fields.Method('get_balance', deserialize='load_balance')
def get_balance(self, obj):
return obj.income - obj.debt
def load_balance(self, value):
return float(value)
schema = UserSchema()
result = schema.load({'balance': '100.00'})
result.data['balance'] # => 100.0
为Method和Function添加上下文
Function和Method序列化时可能需要相关环境信息。可以为schema设置context
属性(dict对象),Function和Method可以访问此字典。
下面的例子判断某个User对象是否是某个Blog对象的作者,以及Blog的title属性是否出现bicycle
单词:
class UserSchema(Schema):
name = fields.String()
# Function fields optionally receive context argument
is_author = fields.Function(lambda user, context: user == context['blog'].author)
likes_bikes = fields.Method('writes_about_bikes')
# Method fields also optionally receive context argument
def writes_about_bikes(self, user):
return 'bicycle' in self.context['blog'].title.lower()
schema = UserSchema()
user = User('Freddie Mercury', '[email protected]')
blog = Blog('Bicycle Blog', author=user)
schema.context = {'blog': blog}
data, errors = schema.dump(user)
data['is_author'] # => True
data['likes_bikes'] # => True
自定义错误信息
字段验证产生的错误信息可以在类级别或实例级别配置。
在类级别时,default_error_messages
可以定义为错误码和错误信息的字典映射:
from marshmallow import fields
class MyDate(fields.Date):
default_error_messages = {
'400001': 'Please provide a valid date.',
}
在Field类实例化时,给error_messages
参数传参(dict对象):
from marshmallow import Schema, fields
class UserSchema(Schema):
name = fields.Str(
required=True,
error_messages={'required': 'Please provide a name.'}
)