上篇文章主要介绍了 flask-restplus
构建 rest api
的主要用法,这篇文章将介绍如何使用此扩展构建 文档
, 实现 文档跟着代码走
.
上一篇文章已经提到, 文档默认是开启的,而且默认挂载到 /
根路由, 在使用 api = Api(app)
的时候, 会有个默认参数 doc='/'
, 这里的 doc
是指定文档地址挂载点的, 还有个参数为 version
, 它的值默认为 1.0
, 表示当前文档的版本, 使用 title
参数可以描述文档标题. 示例代码如下所示:
from flask import Flask from flask_restplus import Api, Resource app = Flask(__name__) api = Api(app, doc='/doc', version='1.0', title='学习 Flask-RESTPlus') @api.route('/hello') class HelloWorld(Resource): def get(self): return {'hello': 'world'} 复制代码
此时 doc
参数设置为 /doc
, 那访问 /doc
就可以访问到文档:
如上所示,文档的标题为 学习 Flask-RESTPlus
, 版本为 1.0
, 并且默认渲染资源路由. 有一点需要注意, 如果是使用 Flask 实例
初始化的 Api
对象, 那么文档的 base_url
为 /
, 但是如果是使用 蓝图
初始化, 并且在初始化蓝图对象时设置了 url_prefix
参数, 那么文档的 base_url
是挂载到蓝图的 url_prefix
上的. 以下代码表示将文档挂载到蓝图根路由, 即 /api/v1
.
api_v1 = Blueprint('api_v1', __name__, url_prefix='/api/v1') api = Api(api_v1, version='1.0', title='API') 复制代码
上一小节中的文档渲染出来为默认的命名空间, 一个命名空间对应一个资源, 它的文档也将列在其命名空间下, 以下为示例:
from flask_restplus import Api, Namespace, Resource app = Flask(__name__) api = Api(app, doc='/', version='1.0', title='待办列表API') todos = Namespace('todos', description='待办列表') practice = Namespace('practice', description='练习') api.add_namespace(todos) api.add_namespace(practice) @todos.route('') class TODOList(Resource): def get(self): return [] @practice.route('') class Practice(Resource): def get(self): return [] 复制代码
渲染出的文档结果如下所示, 可以看到渲染出的文档一目了然:
使用 flask-restplus
提供的 fileds
模型, 将它与 ORM
对象或者自定义类对应,可以很方便渲染响应和请求参数. 其实它是类似于将对象进行序列化的工具, 在请求的时候, 通过模型判断请求参数, 在响应的时候通过模型进行序列化. 同时文档也可以通过模型来渲染需要的请求参数以及响应数据结构.
model = api.model('Model', { 'name': fields.String, 'address': fields.String, 'date_updated': fields.DateTime(dt_format='rfc822'), }) 复制代码
以上创建了一个名为 Model
拥有三个字段的模型, 创建完成后可以使用 api.expect(model)
来渲染请求参数文档, 使用 api.response(mode=model)
来渲染响应数据文档, 这个我们接下来讲.
flask-restplus
提供的 api.expect
用来渲染请求参数, todos.response
用来渲染响应数据,有多个响应, 就可以多次使用此装饰器, 以下代码渲染出的文档效果如下:
@todos.route('') class TODOList(Resource): @todos.expect(model) @todos.response(code=200, model=model, description='请求成功响应') def get(self): return [] 复制代码
如图所示, model
模型已经被自动转化为 json
格式的数据. 同时渲染出的 Swagger
文档还提供了发送请求功能, 也就是右上角的 Try it out
. 如果想要响应模型列表, 可以这样写 todos.response(code=200, model=[model], description='请求成功响应')
, 如果我只需要模型中的部分字段只用于响应, 另一部分字段只用于请求,这就需要使用到 字段属性
了.
模型提供了很多直接对应 Python
数据类型的字段, 以下为部分常用字段:
fields.Integer
表示数字 fields.String
表示字符串 fields.Datetime
表示日期 fields.List
表示列表
fields.List(fields.String)
将列表项字段传入其中即可 etc
除了这些常规字段,如果一个字段对应的值是另一个模型, 类似与数据库 一对一
或者 一对多
的关系, 可以使用 fields.Nested
字段. 使用方式如下:
model = api.model('Model', { 'name': fields.String, 'address': fields.String, 'date_updated': fields.DateTime(dt_format='rfc822'), }) # 直接引用一个模型 another_model = api.model('AnotherModel', { 'model': fields.Nested(model) }) # 引用模型列表 another_model = api.model('AnotherModel', { 'model': fields.List(fields.Nested(model)) }) # 或者 another_model = api.model('AnotherModel', { 'model': fields.Nested(model, as_list=True) }) 复制代码
还有一些其他字段以及高阶用法, 可以参考 文档
类似于 fields.String
或者 fields.Integer
的字段都拥有自己的属性, 如果使用过 SQLalchemy
的话, 它与模型类的字段属性是同一个性质, 可以对属性赋值, 来更加细致的描述当前属性:
required
用来设置是否为必传参数, 默认为 False
readonly
用来设置只读, 表示只有在响应的时候才会出现, 默认为 None
example
用力设置示例, 默认为 None
description
属性用来描述当前字段信息, 默认为 None
部分字段属性同时也提供了参数校验功能, 对于 fields.String
:
enum min_length max_length pattern
对于 fields.Integer
fields.Float
:
min
最小值 max
最大值 exclusiveMin
: 如果为 True
, 则左开区间, 默认为 False
exclusiveMax
: 如果为 True
, 则右开区间, 默认为 False
multiple
: 值必须是这个数的倍数 使用 @todos.expect(model, validate=True)
就可以开启参数验证, 参数验证出错会抛出 400
异常.
parser
进行参数验证 如上所述, 模型是以 json
的方式进行解析的, 如果传入模型进行参数判断, 那也只能校验 json
参数, 所以在 expect
方法中, 除了根据模型, 也可以根据 parser
校验参数. 校验参数的介绍可以看上一篇文章, 或者直接查看 文档 , 使用了 parser
后, 就可以对 表单
, 查询字符串
, 请求头
, 数据类型
等进行校验.
对于 @api.route('/<int:id>')
中的参数, 可以使用 @api.param('id', description='id')
进行渲染. 此装饰器一般用来装饰 资源类
, 上面使用模型的方式一般用来装饰 资源类方法
, 也可以装饰 资源类
, 比如 404
响应, 表示当前类下的每个方法都可能会返回 404
.
使用两篇文章分别介绍了 构建API
和 构建API文档
, 但只是介绍了常用的一些使用方式, 对于更详细和高阶的用法还是需要阅读 文档 . 其实 对象模型
是用来进行序列化的, 我使用起来感觉不太好用, 就只用来生成文档, 对于简单的参数也会用它进行校验. 对于序列化, 我比较喜欢使用 marshmallow
, 它的用法和 对象模型
十分相似, 感兴趣可以去看下 文档 .