Nested 字段
Nested是字段fields中使用较多的。在 Marshmallow 中用于表示嵌套关系的字段。它允许在一个 Schema 中嵌套另一个 Schema,以处理复杂的对象关系。一般情况下可以与Model类中的relationship对应使用。
一对一
在model模块中Account与Profile是一对一关系,与之对应的AccountSchema和ProfileSchema使用如下定义嵌套关系字段
profile = fields.Nested('ProfileSchema', exclude=('account',))
一对多 多对多
在model模块中Account与Project是多对多关系,预支对应的AccountSchema 和 ProjectSchema 嵌套关系,并使用了many参数,另外为了防止在使用过程中出现循环嵌套引用,还是用exclued来排除一些字段。
class ProjectSchema(BaseSchema):
project_name = fields.String(required=True)
project_webhook = fields.String()
hosts = fields.Nested('HostSchema', many=True, exclude=('project',))
accounts = fields.Nested('AccountSchema', many=True, exclude=('projects',))
装饰器
Marshmallow中常用的装饰器有以下几个:
pre_load
: 在反序列化操作之前执行,用于预处理数据。可以在这个装饰器中添加自定义的预处理逻辑,例如对输入数据进行校验、过滤或转换等操作。post_load
: 在反序列化操作之后执行,用于对反序列化后的对象进行进一步处理或验证。可以在这个装饰器中添加自定义的逻辑,例如根据特定的规则对数据进行修正或验证。pre_dump
: 在序列化操作之前执行,用于准备要序列化的数据。可以在这个装饰器中添加自定义的准备逻辑,例如提取特定数据、计算生成序列化数据等。post_dump
: 在序列化操作之后执行,用于对序列化后的数据进行进一步处理或验证。可以在这个装饰器中添加自定义的逻辑,例如对序列化后的数据进行校验、过滤或转换等操作。validates_schema
: 用于验证序列化数据是否符合指定的 Schema(模式)。如果数据不符合模式,则抛出 ValidationError 异常。可以在这个装饰器中添加自定义的验证逻辑,例如根据特定的规则对数据进行验证。
这些装饰器可以用于在 Marshmallow 库的序列化和反序列化过程中添加额外的处理和验证逻辑,以满足特定的业务需求。
数据校验
Marshmallow在反序列化是,最重要的功能之一就是校验数据。
有多种方式进行数据校验:
使用validates_scheme装饰器,可以对整个data进行自定义的校验。
使用validates装饰器,可以指定要校验的field。
在field中使用validate属性。validate类说明,详见官网
下面代码中,
- 使用了validates_schema装饰器,对gender进行校验,并修正大小写。
- 使用validates装饰器校验height字段,并限定最小值。
- age字段在filed字段中使用validate属性,指定数据范围。
class ProfileSchema(BaseSchema):
fullname = fields.String()
gender = fields.String()
account = fields.Nested('AccountSchema', exclude=('profile',))
age = fields.Int(validate=validate.Range(min=18, max=65))
email = fields.Email()
height = fields.Int()
@validates_schema
def validate_profile_gender(self, data, **kwargs):
if data['gender'] not in ['M', 'F', 'f', 'm']:
raise ValidationError(field_name='gender', message='gender must be M or F')
else:
data['gender'] = data['gender'].upper()
return data
@validates('height')
def validate_age(self, data, **kwargs):
if data <= 150:
raise ValidationError('height must be taller than 150')
else:
return data
依据以上代码,如果是不合规数据,经过load操作,会抛出异常。
from app import app
from schema import *
with app.app_context():
p_s = ProfileSchema()
# age 不符合
print("age 不符合")
data = {"fullname": "川普", "gender": "M", "age": '71',"height": "185" }
try:
a = p_s.load(data)
print(a)
except Exception as E:
print(str(E))
# gender 不符合
print("gender 不符合")
data = {"fullname": "川普", "gender": "男", "age": '50',"height": "185" }
try:
a = p_s.load(data)
print(a)
except Exception as E:
print(str(E))
# height 不符合
print("height 不符合")
data = {"fullname": "川普", "gender": "M", "age": '50',"height": "145" }
try:
a = p_s.load(data)
print(a)
except Exception as E:
print(str(E))
# 符合,age 与 height 还被修改为Int
print("符合,age 与 height 还被修改为Int")
data = {"fullname": "川普", "gender": "M", "age": '50',"height": "185" }
try:
a = p_s.load(data)
print(a)
except Exception as E:
print(str(E))