Flask-RESTPlus 中文文档 - 5

499 0

  • Swagger文档
    • 使用@api.doc()装饰器进行文档编辑
    • 模型自动记录
    • @api.marshal_with()装饰器
    • @api.expect()装饰器
    • 使用@api.response装饰器进行文档编辑
    • @api.route()装饰器
    • 对字段进行文档编写
    • 对函数进行文档编写
    • 级联(Cascading)
    • 已弃用标记
    • 隐藏文档
    • 文档授权(Documenting authorizations)
    • 展示支持信息(Expose vendor Extensions)
    • 导出Swagger格式
    • Swagger UI

对函数进行文档编写

每一个资源类都会被记录为一个Swagger路径。

每一个资源类的函数(get , post , put , delete , path , options , head)都会被记录为一个Swagger操作。

您可以使用 id 关键字参数指定唯一的Swagger operationId

@api.route('/my-resource/')
class MyResource(Resource):
    @api.doc(id='get_something')
    def get(self):
        return {}

设置第一个参数也可以达到相同的目的:

@api.route('/my-resource/')
class MyResource(Resource):
    @api.doc('get_something')
    def get(self):
        return {}

如果没有特别指定,默认将以下面的格式设定 operationId

{{verb}}_{{resource class name | camelCase2dashes }}

前面的例子中,默认的 operationId 将会是 get_my_resource

你可以通过给 default_id 传入一个回调函数来覆盖默认的 operationId 生成器。这个回调函数接受下面两个参数:

  • 资源类的类名
  • 小写的HTTP方法
def default_id(resource, method):
    return ''.join((method, resource))

api = Api(app, default_id=default_id)

前面的例子中,生成的 operationId 将会是 getMyResource

每个操作都会自动纳入其命名空间的标签下。如果资源类是直接归属于根目录,则自动纳入默认标签中。

函数参数

来自url地址的参数会自动被记录。你可以通过 api.doc() 修饰器的 params 参数添加额外的内容:

@api.route('/my-resource/<id>', endpoint='my-resource')
@api.doc(params={'id': 'An ID'})
class MyResource(Resource):
    pass

或者使用 api.params 修饰器:

@api.route('/my-resource/<id>', endpoint='my-resource')
@api.param('id', 'An ID')
class MyResource(Resource):
    pass

输入和输出模型

你可以通过 api.doc() 修饰器的 model 关键字指定序列化输出模型。

对于 PUTPOST 方法,使用 body 关键字指定输入模型。

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 {}

如果 bodyformData 同时使用,将会造成 SpecsError 异常。

模型同时也可以被 RequestParser 指定。

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 {}

提示:

解码后的有效载荷(decoded payload)将以字典的形式作为 有效载荷(payload)的属性存在在请求上下文中(request context)。

@api.route('/my-resource/')
class MyResource(Resource):
    def get(self):
        data = api.payload

提示:

更推荐使用 RequestParser 而不是 api.param() 修饰器对表单进行记录,因为前者同时支持表单验证。

头(headers)

你可以使用 api.header() 修饰器快捷记录响应头内容。

@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

如果你要指定一个只出现在响应中的标头,只需要使用 @api.responseheaders 关键字即可。

@api.route('/response-headers/')
class WithHeaderResource(restplus.Resource):
    @api.response(200, 'Success', headers={'X-Header': 'Some header'})
    def get(self):
        pass

记录 期望或者需求(expected/request) 的标头请使用 @api.expect 修饰符。

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

级联(Cascading)

函数的文档优先级高于类的文档,继承的文档高于其父类的文档。

例如,这两个声明是等效的:

  • 函数文档继承类文档内容:

    @api.route('/my-resource/<id>', endpoint='my-resource')
    @api.params('id', 'An ID')
    class MyResource(Resource):
        def get(self, id):
            return {}
    
  • 函数文档覆盖类文档内容:

    @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 {}
    

你也可以用类装饰器指定函数的文档。以下示例将产生与前两个示例相同的文档:

@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 修饰器将资源类或函数标记为已弃用:

# Deprecate the full resource
@api.deprecated
@api.route('/resource1/')
class Resource1(Resource):
    def get(self):
        return {}

# Deprecate methods
@api.route('/resource4/')
class Resource4(Resource):
    def get(self):
        return {}

    @api.deprecated
    def post(self):
        return {}

    def put(self):
        return {}

隐藏文档

用下面的方法你可以将一些资源类或函数从文档种隐藏:

# Hide the full resource
@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 {}

# Hide methods
@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 {}

提示:

没有附加的资源类的命名空间会自动的在文档中隐藏。

文档授权(Documenting authorizations)

你可以通过 authorizations 关键字修改文档授权信息。查看 Swagger授权文档(Swagger Authentication documentation) 了解详细配置方法。

  • authorizations 是以Python字典的形式表现Swagger securityDefinitions 的配置信息。

    authorizations = {
        'apikey': {
            'type': 'apiKey',
            'in': 'header',
            'name': 'X-API-KEY'
        }
    }
    api = Api(app, authorizations=authorizations)
    

配置授权之后每个资源类和方法的解释器均需配置授权:

@api.route('/resource/')
class Resource1(Resource):
    @api.doc(security='apikey')
    def get(self):
        pass

    @api.doc(security='apikey')
    def post(self):
        pass

你可以通过 security 关键字在 Api 的构造函数中全局的应用这个配置:

authorizations = {
    'apikey': {
        'type': 'apiKey',
        'in': 'header',
        'name': 'X-API-KEY'
    }
}
api = Api(app, authorizations=authorizations, security='apikey')

你也可以设置多种授权机制:

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)

安全机制也可以通过特定的函数覆盖:

@api.route('/authorizations/')
class Authorized(Resource):
    @api.doc(security=[{'oauth2': ['read', 'write']}])
    def get(self):
        return {}

你可以通过给 security 关键字传入 None 或一个空列表禁用某个资源类或方法的安全机制:

@api.route('/without-authorization/')
class WithoutAuthorization(Resource):
    @api.doc(security=[])
    def get(self):
        return {}

    @api.doc(security=None)
    def post(self):
        return {}

展示支持信息(Expose vendor Extensions)

Swagger允许你自定义 支持信息(vendor extensions ) ,而Flask-RESTPlus可以通过 @api.vendor 修饰器对其进行设置。

它同时支持 dictkwargs 扩展,并自动执行 x-prefix

@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格式:

from flask import json

from myapp import api

print(json.dumps(api.__schema__))
技术文章 Flask Flask Extension

TOPIC

Flask

关于Flask


Comments 0