简体   繁体   English

装饰器中的参数范围不一致

[英]Inconsistent scope of parameters in decorator

I've written a decorator function for a Flask user permission system. 我已经为Flask用户权限系统编写了一个装饰器函数。 When I try to hit a view decorated with it, I get an UnboundLocalError on the user parameter. 当我尝试用它装饰的视图时,在user参数上出现UnboundLocalError Here's the decorator function: 这是装饰器函数:

def user_is(role, user=None):
    """
    Takes an role (a string name of either a role or an ability) and returns the function if the user has that role
    """
    def wrapper(func):
        @wraps(func)
        def inner(*args, **kwargs):
            from .models import Role
            desired_role = Role.query.filter_by(
                name=role).first()
            if not user:
                try:
                    from flast.ext.login import current_user as user
                except ImportError:
                    raise ImportError(
                        'User argument not passed and Flask-Login current_user could not be imported.')
            if desired_role in user.roles:
                return func(*args, **kwargs)
            else:
                # Make this do someting way better.
                return "You do not have access"
        return inner
    return wrapper

The traceback indicates user is undefined for if not user: . 回溯表明user是未定义if not user: I'm not sure how this can be the case. 我不确定情况如何。 It's my understanding that, if user doesn't exist in the scope for the inner function, Python will go out level-by-level through the nested functions until it finds it. 据我了解,如果user不存在于内部函数的作用域中,Python将逐级遍历嵌套函数,直到找到它为止。 This means I should only get the UnboundLocalError if user is undefined in the function, all functions wrapping it, and globally. 这意味着,如果在函数中未定义user ,所有函数将其包装以及全局未定义,则仅应获取UnboundLocalError This is plainly not the case here. 在这里显然不是这种情况。

Another source of confusion is that I'm able to see using the Werkzeug debug console that my other parameter is defined in this scope. 混乱的另一个原因是,我能看到使用我的其他参数在此范围内定义的WERKZEUG调试控制台。 How can one parameter be defined and the other parameter, which is taken in by the decorator function, be undefined at the same point in the program flow? 如何在程序流程的同一点定义一个参数,而由装饰器函数接受的另一个参数却未定义呢? I thought maybe this was a quirk that only affected parameters with a default value, so I switched it over to a required parameter and manually passed in None , but this still produced the error? 我以为这可能是一个怪癖,只影响具有默认值的参数,所以我将其切换为必需参数并手动传递为None ,但这仍然会产生错误?

Why is user out of scope when the other parameter is in scope? 当另一个参数在范围内时,为什么user不在范围内? How can I fix this decorator? 如何修复此装饰器?

You are importing user in the inner function: 您正在内部功能中导入user

from flast.ext.login import current_user as user

That makes user a local in your inner function and will never be looked up as a closure. 这使user成为您内部函数的本地user ,并且永远不会被视为闭包。

Do not rename the import; 不要重命名导入; instead, assign user to current_user . 而是将user分配给current_user

def user_is(role, user=None):
    """
    Takes an role (a string name of either a role or an ability) and returns the function if the user has that role
    """
    def wrapper(func):
        @wraps(func)
        def inner(*args, **kwargs):
            from .models import Role
            desired_role = Role.query.filter_by(
                name=role).first()
            if not user:
                try:
                    from flast.ext.login import current_user
                except ImportError:
                    raise ImportError(
                        'User argument not passed and Flask-Login current_user could not be imported.')
            else:
                current_user = user
            if desired_role in current_user.roles:
                return func(*args, **kwargs)
            else:
                # Make this do someting way better.
                return "You do not have access"
        return inner
    return wrapper

or perhaps name the outer user to default_user or similar. 或将外部user命名为default_user或类似名称。

Now user is never assigned to in the inner function, and remains a non-local reference to the outer scope. 现在, user永远不会在内部函数中分配给user ,而仍然是对外部作用域的非本地引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM