Swagger API 文档是自动生成的,可从您的 API(path='/)
的 path 对应的值获取。@api.doc()
您可以使用装饰器配置文档。
使用@api.doc()
装饰器记录 装饰器api.doc()
允许您在文档中包含其他信息。可以装饰一个类或方法:
1 2 3 4 5 6 7 8 9 @api.route('/my-resource/<id>', endpoint='my-resource') @api.doc(params={'id': 'An ID'}) class MyResource (Resource) : def get (self, id) : return {} @api.doc(responses={403: 'Not Authorized'}) def post (self, id) : api.abort(403 )
自动记录模型 model()所有使用、实例化的模型clone()都inherit() 将自动记录在您的 Swagger 规范中。可以在 swagger ui 中看到。
model().inherit()
方法将在 Swagger 模型定义中注册父级和子级:
1 2 3 4 5 6 7 8 parent = api.model('Parent' , { 'name' : fields.String, 'class' : fields.String(discriminator=True ) }) child = api.inherit('Child' , parent, { 'extra' : fields.String })
上述配置将产生这些 Swagger 定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 { "Parent" : { "properties" : { "name" : {"type" : "string" }, "class" : {"type" : "string" } }, "discriminator" : "class" , "required" : ["class" ] }, "Child" : { "allOf" : [ { "$ref" : "#/definitions/Parent" }, { "properties" : { "extra" : {"type" : "string" } } } ] } }
@api.marshal_with()
装饰器这个装饰器像原始marshal_with()
装饰器一样工作,不同之处在于它记录了方法。可选参数code
允许您指定预期的 HTTP 状态代码(默认为 200)。可选参数as_list
允许您指定对象是否作为列表返回。
1 2 3 4 5 6 7 8 9 10 11 12 13 resource_fields = api.model('Resource' , { 'name' : fields.String, })@api.route('/my-resource/<id>', endpoint='my-resource') class MyResource (Resource) : @api.marshal_with(resource_fields, as_list=True) def get (self) : return get_objects() @api.marshal_with(resource_fields, code=201) def post (self) : return create_object(), 201
Api.marshal_list_with()
装饰器等价于.Api.marshal_with(fields, as_list=True)()
@api.expect()
装饰器 等效于 @api.doc(body=resource_fields)
装饰器@api.expect()
允许您指定预期的输入字段。它接受一个可选的布尔参数validate
,指示是否应验证有效负载。可以通过将配置RESTPLUS_VALIDATE
设置为True
或传递validate=True
给 API 构造函数来全局自定义验证行为。
以下示例是等效的:
1 2 3 4 5 6 7 8 9 resource_fields = api.model('Resource' , { 'name' : fields.String, })@api.route('/my-resource/<id>') class MyResource (Resource) : @api.expect(resource_fields) def get (self) : pass
1 2 3 4 5 6 7 8 9 resource_fields = api.model('Resource' , { 'name' : fields.String, })@api.route('/my-resource/<id>') class MyResource (Resource) : @api.doc(body=resource_fields) def get (self) : pass
您可以将列表指定为预期输入:
1 2 3 4 5 6 7 8 9 resource_fields = api.model('Resource' , { 'name' : fields.String, })@api.route('/my-resource/<id>') class MyResource (Resource) : @api.expect([resource_fields]) def get (self) : pass
您可以使用RequestParser
来定义预期的输入:
1 2 3 4 5 6 7 8 9 10 parser = api.parser() parser.add_argument('param' , type=int, help='Some param' , location='form' ) parser.add_argument('in_files' , type=FileStorage, location='files' )@api.route('/with-parser/', endpoint='with-parser') class WithParserResource (restplus.Resource) : @api.expect(parser) def get (self) : return {}
可以在特定端点上启用或禁用验证:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 resource_fields = api.model('Resource' , { 'name' : fields.String, })@api.route('/my-resource/<id>') class MyResource (Resource) : @api.expect(resource_fields) def post (self) : pass @api.expect(resource_fields, validate=True) def post (self) : pass
通过配置进行应用程序范围验证的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 app.config['RESTPLUS_VALIDATE' ] = True api = Api(app) resource_fields = api.model('Resource' , { 'name' : fields.String, })@api.route('/my-resource/<id>') class MyResource (Resource) : @api.expect(resource_fields) def post (self) : pass @api.expect(resource_fields, validate=False) def post (self) : pass
通过构造函数进行应用程序范围验证的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 api = Api(app, validate=True ) resource_fields = api.model('Resource' , { 'name' : fields.String, })@api.route('/my-resource/<id>') class MyResource (Resource) : @api.expect(resource_fields) def post (self) : pass @api.expect(resource_fields, validate=False) def post (self) : pass
使用@api.response()
装饰器记录 等效于 @api.doc(responses='...')
装饰器@api.response()
允许您记录已知响应,并且是@api.doc(responses='...')
.
以下两个定义是等价的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @api.route('/my-resource/') class MyResource (Resource) : @api.response(200, 'Success') @api.response(400, 'Validation Error') def get (self) : pass @api.route('/my-resource/') class MyResource (Resource) : @api.doc(responses={ 200 : 'Success' , 400 : 'Validation Error' }) def get (self) : pass
您可以选择将响应模型指定为第三个参数:
1 2 3 4 5 6 7 8 9 model = api.model('Model' , { 'name' : fields.String, })@api.route('/my-resource/') class MyResource (Resource) : @api.response(200, 'Success', model) def get (self) : pass
@api.marshal_with()
装饰器自动记录响应:
1 2 3 4 5 6 7 8 9 10 model = api.model('Model' , { 'name' : fields.String, })@api.route('/my-resource/') class MyResource (Resource) : @api.response(400, 'Validation error') @api.marshal_with(model, code=201, description='Object created') def post (self) : pass
可以在不知道响应代码的情况下指定发送的默认响应:
1 2 3 4 5 @api.route('/my-resource/') class MyResource (Resource) : @api.response('default', 'Error') def get (self) : pass
@api.route()
装饰器doc
您可以使用 的参数提供类范围的文档Api.route()
。Api.doc()
此参数接受与装饰器相同的值。
例如,这两个声明是等价的:
1 2 3 4 5 @api.route('/my-resource/<id>', endpoint='my-resource') @api.doc(params={'id': 'An ID'}) class MyResource (Resource) : def get (self, id) : return {}
1 2 3 4 @api.route('/my-resource/<id>', endpoint='my-resource', doc={'params':{'id': 'An ID'}}) class MyResource (Resource) : def get (self, id) : return {}
每个资源有多个路由 多个Api.route()
装饰器可用于为Resource
. 该doc
参数提供每条路线 的文档。
例如,这里description
仅适用于/also-my-resource/<id>
路线:
1 2 3 4 5 6 7 8 @api.route("/my-resource/<id>") @api.route( "/also-my-resource/<id>" , doc={"description" : "Alias for /my-resource/<id>" }, )class MyResource (Resource) : def get (self, id) : return {}
在这里,该/also-my-resource/<id>
路线被标记为已弃用:
1 2 3 4 5 6 7 8 9 10 11 @api.route("/my-resource/<id>") @api.route( "/also-my-resource/<id>" , doc={ "description" : "Alias for /my-resource/<id>, this route is being phased out in V2" , "deprecated" : True , }, )class MyResource (Resource) : def get (self, id) : return {}
除非明确覆盖,否则应用于Resource
using的文档在所有路由Api.doc()
之间共享:
1 2 3 4 5 6 7 8 9 @api.route("/my-resource/<id>") @api.route( "/also-my-resource/<id>" , doc={"description" : "Alias for /my-resource/<id>" }, )@api.doc(params={"id": "An ID", description="My resource"}) class MyResource (Resource) :def get (self, id) : return {}
在这里,id
来自装饰器的文档@api.doc()
存在于两个路由中, 从 装饰器 /my-resource/<id>
继承描述并用.My resource``@api.doc()``/also-my-resource/<id>``Alias for /my-resource/<id>
带有doc
参数的路线被赋予一个独特的Swagger operationId
。没有参数的路由 doc
具有相同的 Swagger operationId
,因为它们被认为是相同的操作。
记录字段 每个 Flask-Restplus 字段都接受用于记录该字段的可选参数:
required
:一个布尔值,指示该字段是否始终设置(默认 False
值:)
description
:有关该字段的一些详细信息(默认 None
值:)
example
:显示时使用的示例(_默认_:)None
还有特定于字段的属性:
该String
字段接受以下可选参数:
enum
:限制授权值的数组。
min_length
:预期的最小长度。
max_length
:预期的最大长度。
pattern
: 用于验证字符串的 RegExp 模式。
Integer
和字段Float
接受以下Arbitrary
可选参数:
min
: 限制可接受的最小值。
max
: 限制最大接受值。
exclusiveMin
: 如果True
, 最小值不在允许的区间内。
exclusiveMax
: 如果True
, 最大值不在允许的区间内。
multiple
:指定数字必须是该值的倍数。
The DateTime
field accepts the min
, max
, exclusiveMin
and exclusiveMax
optional arguments. These should be dates or datetimes (either ISO strings or native objects).
1 2 3 4 5 my_fields = api.model('MyModel' , { 'name' : fields.String(description='The name' , required=True ), 'type' : fields.String(description='The object type' , enum=['A' , 'B' ]), 'age' : fields.Integer(min=0 ), })
记录方法 每个资源都将记录为 Swagger 路径。
每个资源方法 ( get
, post
, put
, delete
, path
, options
, head
) 都将记录为 Swagger 操作。
operationId
您可以使用id
关键字参数指定唯一的 Swagger :
1 2 3 4 5 @api.route('/my-resource/') class MyResource (Resource) : @api.doc(id='get_something') def get (self) : return {}
您也可以将第一个参数用于相同目的:
1 2 3 4 5 @api.route('/my-resource/') class MyResource (Resource) : @api.doc('get_something') def get (self) : return {}
如果未指定,operationId
则使用以下模式提供默认值:
1 {{verb}}_{{resource class name | camelCase2dashes }}
在前面的示例中,默认生成的operationId
是get_my_resource
.
operationId
您可以通过为参数提供可调用对象来覆盖默认生成器default_id
。此可调用对象接受两个位置参数:
1 2 3 4 def default_id (resource, method) : return '' .join((method, resource)) api = Api(app, default_id=default_id)
在前面的示例中,生成的operationId
将是getMyResource
.
每个操作都会自动接收命名空间标签。如果资源附加到根 API,它将接收默认命名空间标签。
方法参数 URL 路径中的参数会自动记录。您可以使用装饰器的params
关键字参数提供其他信息:api.doc()
1 2 3 4 @api.route('/my-resource/<id>', endpoint='my-resource') @api.doc(params={'id': 'An ID'}) class MyResource (Resource) : pass
或使用api.param
快捷方式装饰器:
1 2 3 4 @api.route('/my-resource/<id>', endpoint='my-resource') @api.param('id', 'An ID') class MyResource (Resource) : pass
输入和输出模型 您可以使用装饰器的model
关键字参数指定序列化输出模型。api.doc()
对于POST
和PUT
方法,使用body
关键字参数来指定输入模型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 fields = api.model('MyModel' , { 'name' : fields.String(description='The name' , required=True ), 'type' : fields.String(description='The object type' , enum=['A' , 'B' ]), 'age' : fields.Integer(min=0 ), })@api.model(fields={'name': fields.String, 'age': fields.Integer}) class Person (fields.Raw) : def format (self, value) : return {'name' : value.name, 'age' : value.age}@api.route('/my-resource/<id>', endpoint='my-resource') @api.doc(params={'id': 'An ID'}) class MyResource (Resource) : @api.doc(model=fields) def get (self, id) : return {} @api.doc(model='MyModel', body=Person) def post (self, id) : return {}
如果同时使用body
和formData
参数,将引发 SpecsError
。
模型也可以用RequestParser
.
1 2 3 4 5 6 7 8 9 parser = api.parser() parser.add_argument('param' , type=int, help='Some param' , location='form' ) parser.add_argument('in_files' , type=FileStorage, location='files' )@api.route('/with-parser/', endpoint='with-parser') class WithParserResource (restplus.Resource) : @api.expect(parser) def get (self) : return {}
解码后的有效负载将作为请求上下文中有效负载属性中的字典提供。
1 2 3 4 @api.route('/my-resource/') class MyResource (Resource) : def get (self) : data = api.payload
Using RequestParser
优于api.param()
装饰器来记录表单字段,因为它也执行验证。
标题 @api.header()
您可以使用装饰器快捷方式记录响应标头。
1 2 3 4 5 6 @api.route('/with-headers/') @api.header('X-Header', 'Some class header') class WithHeaderResource (restplus.Resource) : @api.header('X-Collection', type=[str], collectionType='csv') def get (self) : pass
如果您需要指定仅出现在 gvien 响应中的标头,只需使用@api.response headers参数。
1 2 3 4 5 @api.route('/response-headers/') class WithHeaderResource (restplus.Resource) : @api.response(200, 'Success', headers={'X-Header': 'Some header'}) def get (self) : pass
记录预期/请求标头是通过@api.expect装饰器完成的
1 2 3 4 5 6 7 8 parser = api.parser() parser.add_argument('Some-Header' , location='headers' )@api.route('/expect-headers/') @api.expect(parser) class ExpectHeaderResource (restplus.Resource) : def get (self) : pass
级联 方法文档优先于类文档,继承文档优先于父文档。
例如,这两个声明是等价的:
1 2 3 4 5 @api.route('/my-resource/<id>', endpoint='my-resource') @api.params('id', 'An ID') class MyResource (Resource) : def get (self, id) : return {}
1 2 3 4 5 6 @api.route('/my-resource/<id>', endpoint='my-resource') @api.param('id', 'Class-wide description') class MyResource (Resource) : @api.param('id', 'An ID') def get (self, id) : return {}
您还可以从类装饰器中提供特定于方法的文档。以下示例将生成与前两个示例相同的文档:
1 2 3 4 5 6 @api.route('/my-resource/<id>', endpoint='my-resource') @api.params('id', 'Class-wide description') @api.doc(get={'params': {'id': 'An ID'}}) class MyResource (Resource) : def get (self, id) : return {}
标记为已弃用 @api.deprecated
@api.deprecated
您可以使用装饰器将资源或方法标记为已弃用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @api.deprecated @api.route('/resource1/') class Resource1 (Resource) : def get (self) : return {}@api.route('/resource4/') class Resource4 (Resource) : def get (self) : return {} @api.deprecated def post (self) : return {} def put (self) : return {}
隐藏文档 您可以使用以下任何方法从文档中隐藏一些资源或方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 @api.route('/resource1/', doc=False) class Resource1 (Resource) : def get (self) : return {}@api.route('/resource2/') @api.doc(False) class Resource2 (Resource) : def get (self) : return {}@api.route('/resource3/') @api.hide class Resource3 (Resource) : def get (self) : return {}@api.route('/resource4/') @api.doc(delete=False) class Resource4 (Resource) : def get (self) : return {} @api.doc(False) def post (self) : return {} @api.hide def put (self) : return {} def delete (self) : return {}
没有附加资源的命名空间标签将自动从文档中隐藏。
记录授权 您可以使用authorizations
关键字参数来记录授权信息。有关配置详细信息,请参阅Swagger 身份验证文档 。
authorizations
是 SwaggersecurityDefinitions
配置的 Python 字典表示。
1 2 3 4 5 6 7 8 authorizations = { 'apikey' : { 'type' : 'apiKey' , 'in' : 'header' , 'name' : 'X-API-KEY' } } api = Api(app, authorizations=authorizations)
然后装饰每个需要授权的资源和方法:
1 2 3 4 5 6 7 8 9 @api.route('/resource/') class Resource1 (Resource) : @api.doc(security='apikey') def get (self) : pass @api.doc(security='apikey') def post (self) : pass
security
您可以使用构造函数上的参数全局应用此要求Api
:
1 2 3 4 5 6 7 8 authorizations = { 'apikey' : { 'type' : 'apiKey' , 'in' : 'header' , 'name' : 'X-API-KEY' } } api = Api(app, authorizations=authorizations, security='apikey' )
您可以有多个安全方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 authorizations = { 'apikey' : { 'type' : 'apiKey' , 'in' : 'header' , 'name' : 'X-API' }, 'oauth2' : { 'type' : 'oauth2' , 'flow' : 'accessCode' , 'tokenUrl' : 'https://somewhere.com/token' , 'authorizationUrl' : 'https://somewhere.com/auth' , 'scopes' : { 'read' : 'Grant read-only access' , 'write' : 'Grant read-write access' , } } } api = Api(self.app, security=['apikey' , {'oauth2' : 'read' }], authorizations=authorizations)
可以为特定方法覆盖安全方案:
1 2 3 4 5 @api.route('/authorizations/') class Authorized (Resource) : @api.doc(security=[{'oauth2': ['read', 'write']}]) def get (self) : return {}
None
您可以通过传递或空列表作为security
参数来禁用给定资源或方法的安全性:
1 2 3 4 5 6 7 8 9 @api.route('/without-authorization/') class WithoutAuthorization (Resource) : @api.doc(security=[]) def get (self) : return {} @api.doc(security=None) def post (self) : return {}
公开供应商扩展 Swaggers 允许您公开自定义供应商扩展 ,您可以在 Flask-RESTPlus 中使用它们和@api.vendor装饰器。
它支持dict或kwargs两种扩展,并执行自动x-前缀:
1 2 3 4 5 6 7 8 9 @api.route('/vendor/') @api.vendor(extension1='any authorized value') class Vendor (Resource) : @api.vendor({ 'extension-1' : {'works' : 'with complex values' }, 'x-extension-3' : 'x- prefix is optionnal' , }) def get (self) : return {}
导出 Swagger 规范 您可以为您的 API 导出 Swagger 规范:
1 2 3 4 5 from flask import jsonfrom myapp import api print(json.dumps(api.__schema__))
swagger 用户界面 默认flask-restplus
提供 Swagger UI 文档,从 API 的根 URL 提供。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from flask import Flaskfrom flask_restplus import Api, Resource, fields app = Flask(__name__) api = Api(app, version='1.0' , title='Sample API' , description='A sample API' , )@api.route('/my-resource/<id>') @api.doc(params={'id': 'An ID'}) class MyResource (Resource) : def get (self, id) : return {} @api.response(403, 'Not Authorized') def post (self, id) : api.abort(403 )if __name__ == '__main__' : app.run(debug=True )
如果您运行下面的代码并访问 API 的根 URL ( http://localhost:5000 ),您可以查看自动生成的 Swagger UI 文档。
定制 您可以使用参数控制 Swagger UI 路径doc
(默认为 API 根目录):
1 2 3 4 5 6 7 8 9 10 from flask import Flask, Blueprintfrom flask_restplus import Api app = Flask(__name__) blueprint = Blueprint('api' , __name__, url_prefix='/api' ) api = Api(blueprint, doc='/doc/' ) app.register_blueprint(blueprint)assert url_for('api.doc' ) == '/api/doc/'
您可以通过设置指定自定义验证器 URL config.SWAGGER_VALIDATOR_URL
:
1 2 3 4 5 6 7 from flask import Flaskfrom flask_restplus import Api app = Flask(__name__) app.config.SWAGGER_VALIDATOR_URL = 'http://domain.com/validator' api = Api(app)
您可以启用 [OAuth2 隐式流程]( https://oauth.net/2/grant-types/implicit/ ) 以检索授权令牌,以便在 Swagger UI 中以交互方式测试 api 端点。config.SWAGGER_UI_OAUTH_CLIENT_ID
和将 特定于您的 OAuth2 IDP 配置authorizationUrl
。scopes
领域字符串作为查询参数添加到 authorizationUrl 和 tokenUrl。这些价值观都是公共知识。此处未指定_客户端密码。_.. 使用 PKCE 而不是隐式流取决于https://github.com/swagger-api/swagger-ui/issues/5348
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from flask import Flask app = Flask(__name__) app.config.SWAGGER_UI_OAUTH_CLIENT_ID = 'MyClientId' app.config.SWAGGER_UI_OAUTH_REALM = '-' app.config.SWAGGER_UI_OAUTH_APP_NAME = 'Demo' api = Api( app, title=app.config.SWAGGER_UI_OAUTH_APP_NAME, security={'OAuth2' : ['read' , 'write' ]}, authorizations={ 'OAuth2' : { 'type' : 'oauth2' , 'flow' : 'implicit' , 'authorizationUrl' : 'https://idp.example.com/authorize?audience=https://app.example.com' , 'clientId' : app.config.SWAGGER_UI_OAUTH_CLIENT_ID, 'scopes' : { 'openid' : 'Get ID token' , 'profile' : 'Get identity' , } } } )
您还可以使用config.SWAGGER_UI_DOC_EXPANSION
设置('none'
或'list'
)指定初始扩展状态'full'
:
1 2 3 4 5 6 7 from flask import Flaskfrom flask_restplus import Api app = Flask(__name__) app.config.SWAGGER_UI_DOC_EXPANSION = 'list' api = Api(app)
默认情况下,操作 ID 和请求持续时间是隐藏的,您可以分别启用它们:
1 2 3 4 5 6 7 8 from flask import Flaskfrom flask_restplus import Api app = Flask(__name__) app.config.SWAGGER_UI_OPERATION_ID = True app.config.SWAGGER_UI_REQUEST_DURATION = True api = Api(app)
如果需要自定义 UI,可以使用documentation()
装饰器注册自定义视图功能:
1 2 3 4 5 6 7 8 9 from flask import Flaskfrom flask_restplus import Api, apidoc app = Flask(__name__) api = Api(app)@api.documentation def custom_ui () : return apidoc.ui_for(api)
配置“试用” 默认情况下,所有路径和方法都有一个“试用”按钮,用于在浏览器中执行 API 请求。这些可以通过配置选项按方法禁用,支持与 Swagger UI 参数 SWAGGER_SUPPORTED_SUBMIT_METHODS
相同的值。supportedSubmitMethods
1 2 3 4 5 6 7 8 9 10 11 12 from flask import Flaskfrom flask_restplus import Api app = Flask(__name__) app.config.SWAGGER_SUPPORTED_SUBMIT_METHODS = [] app.config.SWAGGER_SUPPORTED_SUBMIT_METHODS = ["get" , "post" ] api = Api(app)
禁用文档 要完全禁用 Swagger UI,请设置doc=False
:
from flask import Flask
from flask_restplus import Api
app = Flask(__name__)
api = Api(app, doc=False)