0

我为 Flask 用户权限系统编写了一个装饰器函数。当我尝试点击一个用它装饰的视图时,我得到一个UnboundLocalError参数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 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

回溯指示user未定义if not user:。我不确定这是怎么回事。我的理解是,如果user内部函数的作用域中不存在,Python 会逐级遍历嵌套函数,直到找到为止。这意味着我应该只获取函数中未定义的UnboundLocalErrorif user、包装它的所有函数以及全局。这显然不是这里的情况。

另一个令人困惑的原因是,我可以使用 Werkzeug 调试控制台看到我的其他参数在此范围内定义的。如何在程序流程的同一点定义一个参数而装饰器函数接收的另一个参数未定义?我想这可能是一个怪癖,只影响具有默认值的参数,所以我将其切换为必需参数并手动传入None,但这仍然产生错误?

当另一个参数在范围内时,为什么user超出范围?我该如何修复这个装饰器?

4

1 回答 1

3

您正在导入user内部函数:

from flast.ext.login import current_user as user

这会user在您的内部函数中生成一个本地函数,并且永远不会被视为闭包。

不要重命名导入;相反,分配usercurrent_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

或者也许将外部命名userdefault_user或类似。

Nowuser永远不会在内部函数中分配,并且仍然是对外部范围的非本地引用。

于 2013-09-21T14:53:39.913 回答