首页 > 解决方案 > python 装饰器用另一个装饰器包装并修改函数 args

问题描述

我正在为我的 api 使用flask-restx
(a)@namespace.expect(schema)装饰器生成自动文档,
(b) 和RequestParser解析器

这里输入的请求是运行良好并实现 (a) 和 (b) 的代码:

ns = api.namespace('my-api')

@ns.route('/my/api')
class MyApi(Resource):
    schema = read_schema(schema_name)
    @ns.expect(self.schema_model(schema_name, schema), validate=True)
    def post(self):
        parser = RequestParser()
        parser.add_argument('aaa', type=inputs.datetime_from_iso8601)
        parser.add_argument('bbb', type=int)
        parser.parse_args()
        do_something(args['aaa'], args['bbb'])

为了防止为每个 api 编写解析器,我决定扩展flask_restx.Namespace类,并添加我自己的装饰器,它将:
(a)@expect在函数上添加装饰器
(b)从模式生成解析器并将解析的 args 添加到post功能_

这是类的实现:

from flask_restx import Namespace

class RestNamespace(Namespace):

    def schema(self, schema_name, parse=False):
        schema_name = schema_name
        schema = get_api_schema(schema_name)
        parser = build_parser(schema)

        def decorator(f):
            @functools.wraps(f)
            def wrapper(*args, **kwargs):
                if parse:
                    req_args = parser.parse_args()
                    return f(*args, req_args, **kwargs)

                return f(*args, **kwargs)

            return wrapper

        return self.expect(self.schema_model(schema_name, schema), validate=True)(decorator)

# -- usage -----:

ns = RestNamespace('my-api', api=api)

@ns.route('/my/api')
class MyApi(Resource):
    @ns.schema(schema_name, parse=True)
    def post(self, args):
        do_something(args['aaa'], args['bbb'])

不幸的是,当我这样做时self.expect(..),装饰器中的返回没有给出结果(没有文档出现),解析(包装器函数)运行良好

如果我替换
return self.expect(self.schema_model(schema_name, schema), validate=True)(decorator)

return self.expect(self.schema_model(schema_name, schema), validate=True)
then 文档确实出现了,但是解析的内部包装没有效果

一个装饰器用另一个装饰器包装给定函数修改函数参数的正确方法是什么?

标签: pythonflaskpython-decoratorsflask-restx

解决方案


推荐阅读