数据模式¶
请先阅读基础使用章节中这一节及后续内容来了解编写输入输出模式的基础知识。
数据模式的基本概念:
- APIFlask 的
apiflask.Schema基类直接从 marshmallow 导入,带有一些细微改动,详见 API 文档 。 - 我们建议分开定义输入和输出模式。由于输出数据不需要验证,因此无需在输出字段上定义验证器。
apiflask.fields包含了 marshmallow、webargs 和 flask-marshmallow 提供的所有字段(某些别名已被移除)。apiflask.validators包含marshmallow.validate中的所有验证器。- 对于其他函数/类,直接从 marshmallow 导入即可。
- 建议在空闲时阅读marshmallow 的文档 。
反序列化(load)和序列化(dump)¶
在 APIFlask(marshmallow)中,解析和验证输入请求数据的过程称为反序列化(我们从请求中 load 数据)。而格式化输出响应数据的过程称为序列化(我们将数据 dump 到响应中)。
注意我们使用 "load" 和 "dump" 来表示这两个过程。创建模式时,我们使用 load_default 参数为输入模式中的字段设置默认值,使用 dump_default 参数为输出模式中的字段设置默认值。
有四个装饰器用于在 load/dump 过程中注册回调方法:
pre_load:注册在解析/验证请求数据之前调用的方法post_load:注册在解析/验证请求数据之后调用的方法pre_dump:注册在格式化视图函数返回值之前调用的方法post_dump:注册在格式化视图函数返回值之后调用的方法
还有两个装饰器用于注册验证方法:
validates(field_name):注册验证指定字段的方法validates_schema:注册验证整个模式的方法
Tip
使用 validates_schema 时,注意 skip_on_field_errors 默认设为 True:
如果 skip_on_field_errors=True,当验证字段时检测到验证错误时,这个验证方法将被跳过。
直接从 marshmallow 导入这些装饰器:
from marshmallow import pre_load, post_dump, validates
数据字段¶
APIFlask 的 apiflask.fields 模块包含了来自 marshmallow、webargs 和 Flask-Marshmallow 的所有数据字段。我们建议从 apiflask.fields 模块导入它们:
from apiflask.fields import String, Integer
或者你也可以这样引用:
from apiflask import Schema, fields
class FooBar(Schema):
foo = fields.String()
bar = fields.Integer()
部分字段别名已被移除
以下字段别名已被移除:
StrIntBoolUrlUrlForAbsoluteUrlFor
请改用:
StringIntegerBooleanURLURLForAbsoluteURLFor
详见 apiflask#63 和 marshmallow#1828。
marshmallow 字段¶
API 文档:https://marshmallow.readthedocs.io/en/stable/marshmallow.fields.html
AwareDateTimeBooleanConstantDateDateTimeDecimalDictEmailFieldFloatFunctionIntegerIPIPv4IPv6ListMappingMethodNaiveDateTimeNestedNumberPluckRawStringTimeTimeDeltaTupleURLUUID
Flask-Marshmallow 字段¶
API 文档:https://flask-marshmallow.readthedocs.io/en/latest/#flask-marshmallow-fields
AbsoluteURLForHyperlinksURLForFileConfig
webargs 字段¶
API 文档:https://webargs.readthedocs.io/en/latest/api.html#module-webargs.fields
DelimitedListDelimitedTuple
APIFlask 字段¶
API 文档:https://apiflask.com/api/fields
File: represents a file input.Config: dump a config value from Flask'sconfigobject.
Tip
如果现有字段不能满足你的需求,你也可以创建自定义字段。
数据验证器¶
APIFlask 的 apiflask.validators 包含了 marshmallow 提供的所有验证器类以及额外的 FileType 和 FileSize 验证器:
ContainsNoneOfContainsOnlyEmailEqualLengthNoneOfOneOfPredicateRangeRegexpURLValidatorFileTypeFileSize
详细用法请参阅 marshmallow 的 API 文档以及 APIFlask 的 API documentation。
为字段指定验证器时,你可以向 validate 参数传递单个验证器:
from apiflask import Schema
from apiflask.fields import String
from apiflask.validators import OneOf
class PetIn(Schema):
category = String(required=True, validate=OneOf(['dog', 'cat']))
或传递一个验证器列表:
from apiflask import Schema
from apiflask.fields import String
from apiflask.validators import Length, OneOf
class PetIn(Schema):
category = String(required=True, validate=[OneOf(['dog', 'cat']), Length(0, 10)])
Tip
如果现有验证器不能满足你的需求,你也可以创建自定义验证器。
模式名称解析器¶
Version >= 0.9.0
此功能在 0.9.0 版本中添加。
每个模式的 OpenAPI 模式名称都基于解析器函数来解析,以下是 APIFlask 中使用的默认模式名称解析器:
def schema_name_resolver(schema):
name = schema.__class__.__name__ # 获取模式类名
if name.endswith('Schema'): # 移除 "Schema" 后缀
name = name[:-6] or name
if schema.partial: # 为部分模式添加 "Update" 后缀
name += 'Update'
return name
你可以通过设置 APIFlask.schema_name_resolver 属性来提供自定义的模式名称解析器:
from apiflask import APIFlask
def my_schema_name_resolver(schema):
name = schema.__class__.__name__
if name.endswith('Schema'):
name = name[:-6] or name
if schema.partial:
name += 'Partial'
return name
app = APIFlask(__name__)
app.schema_name_resolver = my_schema_name_resolver
模式名称解析器应该接受模式对象作为参数并返回名称。
基础响应模式自定义¶
Version >= 0.9.0
此功能在 0.9.0 版本中添加。
当你使用 output 装饰器设置视图函数的输出时,你需要返回与传递给 output 装饰器的模式相匹配的对象或字典。然后,APIFlask 会将返回值序列化到响应体中:
{
"id": 2,
"name": "Kitty",
"category": "cat"
}
然而,你可能希望将输出数据插入到一个 data 字段中,并添加一些元数据字段。这样你就可以为所有端点返回统一的响应。例如,让所有响应采用以下格式:
{
"data": {
"id": 2,
"name": "Kitty",
"category": "cat"
},
"message": "some message",
"code": "custom code"
}
要实现这一点,你需要设置一个基础响应模式,然后将其传递给配置变量 BASE_RESPONSE_SCHEMA:
from apiflask import APIFlask, Schema
from apiflask.fields import String, Integer, Field
app = APIFlask(__name__)
class BaseResponse(Schema):
data = Field() # data 键
message = String()
code = Integer()
app.config['BASE_RESPONSE_SCHEMA'] = BaseResponse
默认的 data 键是 "data",你可以通过配置变量 BASE_RESPONSE_DATA_KEY 将其更改为与你的模式中的数据字段名称相匹配:
app.config['BASE_RESPONSE_DATA_KEY'] = 'data'
现在你可以在视图函数中返回与基础响应模式相匹配的字典:
class PetOut(Schema):
id = Integer()
name = String()
category = String()
@app.output(PetOut)
def get_pet():
data = {'id': 2, 'name': 'Kitty', 'category': 'cat'}
return {
'data': data,
'message': 'Success!',
'code': 200
}
查看完整示例应用 了解更多详情,运行示例应用请参阅示例页面 。
使用 dataclass 作为数据模式¶
借助 marshmalow-dataclass ,你可以定义 dataclass 然后将其转换为 marshmallow 模式。
$ pip install marshmallow-dataclass
你可以使用 marshmallow-dataclass 中的 dataclass 装饰器来创建数据类,然后调用 .Schema 属性获取相应的 marshmallow 模式:
from dataclasses import field
from apiflask import APIFlask
from apiflask.validators import Length, OneOf
from marshmallow_dataclass import dataclass
app = APIFlask(__name__)
@dataclass
class PetIn:
name: str = field(
metadata={'required': True, 'validate': Length(min=1, max=10)}
)
category: str = field(
metadata={'required': True, 'validate': OneOf(['cat', 'dog'])}
)
@dataclass
class PetOut:
id: int
name: str
category: str
@app.post('/pets')
@app.input(PetIn.Schema, arg_name='pet')
@app.output(PetOut.Schema, status_code=201)
def create_pet(pet: PetIn):
return {
'id': 0,
'name': pet.name,
'category': pet.category
}
查看完整示例应用 了解更多详情。运行示例应用请参阅示例页面。
阅读 mashmallow-dataclass 的文档 和 dataclasses 了解更多信息。