Swagger 是一个 API 文档生成和可视化工具。它基于 OpenAPl(以前称为 Swagger)规范,用于描述 API 的结构、操作、参数和响应。Swagger 可以生成 API 文档,包括 API 端点、请求参数、响应示例等信息。开发人员可以使用 Swagger 文档来了解如何使用 AP1,并进行自助式测试。Swagger 还提供了一些其他功能,如代码生成、Mock 服务器等。
安装:
pip install apispec flask-apispec flask-restful-swagger PyYAML |
在构建 Flask App 对象的地方添加以下内容:
from apispec import APISpec | |
from apispec.ext.marshmallow import MarshmallowPlugin | |
from flask_apispec import FlaskApiSpec | |
from flask_restful_swagger import swagger | |
api = swagger.docs(Api(app), apiVersion='0.1') | |
app.config.update({ | |
'APISPEC SPEC': APISpec( | |
title='Flask Restful API project', | |
version='v1', | |
plugins=[MarshmallowPlug()], | |
openapi_version='2.0' | |
), | |
'APISPEC SWAGGER URL': '/swagger/', # 当前 API 文档的访问路径 | |
'APISPEC_SWAGGER_UI_URL': '/swagger-ui/' # Swagger UI 的访问路径 | |
}) | |
docs = FlaskApiSpec(app) |
# Swagger 生成 API 文档
使用 doc 注解为 swagger 文档生成描述内容。以 BookResource
为例:
from flask_apispec import MethodResource, doc | |
class BookResource(MethodResource, Resource): | |
@doc(description="根据book_id查询一本书的信息", tags=['Book Requests']) | |
def get(self, book_id: int): | |
""" | |
其他代码省略 | |
""" | |
docs.register(BookResource) |
让 BookResource
继承 MethodResource
,然后添加 doc()
注解,最后注册即可。
打开 Swagger UI 的界面可以看到以下内容:
我们可以在这里直接发送请求来查看返回结果,例如 BookResource
的 GET 请求:
# 补充如何生成 .yaml
格式的文档。
因为默认生成的是 json 格式 Swagger 文档,想生成 yaml 格式需要添加一个路由,还是以 BookResouce
为例:
@app.route('/swagger.yaml') | |
def generate_swagger_yaml(): | |
yaml_doc = docs.spec.to_yaml() | |
return Response(yaml_doc, mimetype='text/yaml') |
# Swagger 中的请求和响应
上面生成了 Swagger UI 的界面并且有一些简单演示,这里主要完善文档里 Parameters 和 Responses 两个参数。
继续以 BookResource
为例,定义如下 schema 类来告诉 Swagger 请求里面要有哪些参数:
class TokenSchema(Schema): | |
token = fields.String(required=True, description='Token') | |
class BookRequestSchema(Schema): | |
name = fields.String(required=True, description='书名') | |
author = fields.String(required=True, description='作者') | |
publish_time = fields.DateTime(required=True, description='出版时间') | |
class BookResource(MethodResource, Resource): | |
# 省略代码 | |
@token_required() | |
@doc(description="根据书的id修改书的信息", tags=['Book Requests']) | |
@use_kwargs(BookRequestSchema, location='json') | |
@use_kwargs(TokenSchema, location='headers') | |
def put(self, book_id: int, **kwargs): | |
""" | |
根据书的id修改书的信息 | |
:param book_id: 书的id | |
:return: 修改后的信息 | |
""" | |
try: | |
name = kwargs.get('name', None) | |
author = kwargs.get('author', None) | |
publish_time = kwargs.get('publish_time', None) | |
book_model = BookModel(id=book_id, name=name, author=author, publish_time=publish_time) | |
book_model = BookService().update_book(book_model) | |
return book_model.serialize() | |
except Exception as error: | |
return {'error': f'{error}'}, 400 |
这里我修改了之前的 put()
方法,为了简化代码没有用 request 来提取。两个 schema
注解来提取参数和 token。
回到 Swagger UI 可以看到界面和之前有很大的改变,这样可以在这里做测试了。
那么现在还有 Response 没有默认显示,这里完善文档生成代码,可以在未调用前就知道这个请求应该返回什么格式。
以刚才的 PUT 请求为例,这里返回的是 SQLAlchemy
的数据,定义如下 schema 类:
class BookModelSchema(SQLAlchemyAutoSchema): | |
class Meta: | |
model = BookModel | |
load_instance = True | |
class BookResource(MethodResource, Resource): | |
@doc(description="根据book_id查询一本书的信息", tags=['Book Requests']) | |
@marshal_with(BookModelSchema, code=200, description='id为<book_id>书的信息') | |
def get(self, book_id: int): | |
""" | |
根据book_id查询一本书的信息 | |
:param book_id: 书的id | |
:return: id为<book_id>书的信息 | |
""" | |
book_model = BookService().get_book_by_id(book_id) | |
if book_model: | |
return book_model | |
else: | |
return {'error': f'Book not found for {book_id}'}, 404 |
这里添加了 marshal_with()
注解来返回状态码为 200 的 Response 显示。
最终的 Swagger UI 界面如下所示: