在多个装饰器之间传递参数

时间:2018-02-06 10:29:37

标签: python python-3.x

我使用两个装饰器来装饰一个函数“add_user”,第一个@auth_user通过json web token请求头对登录用户进行身份验证,并将用户信息作为参数“user_info”返回给装饰函数add_user。第二个装饰器@has_permission应该检查用户是否对所请求的资源具有权限。我想将@auth_user作为user_info返回的用户信息传递给@has_permission,但不知道如何做到这一点,到目前为止这是代码:

<p>Hello, <em>how are you doing</em>?</p><p>I admit <strong>I am not fine</strong>, it&#39;s not working...</p>

装饰者:

@has_permission
@auth_user
def add_user(user_info):
    """
    do something
    """
    return None

和我要访问user_info的第二个装饰器:

def auth_user(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        data = jwt.decode(request.headers['some-access-token'], some_secret_key)
        try:
            user_info = User.query.filter(User.id==data['user_id']).first()
        except:
            return jsonify({"message" : "error"}), 401

        return f(user_info, *args, **kwargs)

    return wrapper

实现这一目标的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

在一些帮助下,我设法让这个工作,主要问题是装饰器的顺序/顺序。在问题中; @has_permission将@auth_user作为参数,@ auth_user将原始函数add_user作为参数,如下所示:

has_permission(auth_user(add_user(user_info)))

这意味着当返回参数时,最外面的装饰器@has_permission将返回@auth_user的参数,然后返回add_user。这意味着@has_permission无法访问@auth_user返回的user_info,因此我修改了原始函数:

@auth_user
@has_permission    
def add_user(user_info):
    """
    do something
    """
    return None

现在将以正确的顺序调用装饰器,如下所示:

auth_user(has_permission(add_user(user_info)))

我还更改了@auth_user注入user_info的方式,并将其更改为kwargs而不是args以在@has_permission中访问它:

def auth_user(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        data = jwt.decode(request.headers['some-access-token'], some_secret_key)
        try:
            user_info = User.query.filter(User.id==data['user_id']).first()
        except:
            return jsonify({"message" : "error"}), 401
        kwargs['user_info'] = user_info
        return f(*args, **kwargs)

    return wrapper

最后将user_info传递给原始函数:

def has_permission(f):
    wraps(f)
    def wrapper(*args, **kwargs):
        #access user info
        user_info = kwargs['user_info']
        return f(user_info, *args, **kwargs)
    return wrapper

希望这有助于某人!