使用 Flask-RESTPlus 构建 Swagger API 文档

上篇文章主要介绍了 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 后, 就可以对 表单 , 查询字符串 , 请求头 , 数据类型 等进行校验.

url 参数渲染

对于 @api.route('/<int:id>') 中的参数, 可以使用 @api.param('id', description='id') 进行渲染. 此装饰器一般用来装饰 资源类 , 上面使用模型的方式一般用来装饰 资源类方法 , 也可以装饰 资源类 , 比如 404 响应, 表示当前类下的每个方法都可能会返回 404 .

总结

使用两篇文章分别介绍了 构建API构建API文档 , 但只是介绍了常用的一些使用方式, 对于更详细和高阶的用法还是需要阅读 文档 . 其实 对象模型 是用来进行序列化的, 我使用起来感觉不太好用, 就只用来生成文档, 对于简单的参数也会用它进行校验. 对于序列化, 我比较喜欢使用 marshmallow , 它的用法和 对象模型 十分相似, 感兴趣可以去看下 文档 .

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章