我为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将通过嵌套函数逐级出去,直到找到它为止。这意味着如果UnboundLocalError
在函数中未定义,包含它的所有函数和全局函数,我应该只获取user
。这显然不是这种情况。
另一个混乱的原因是我能够看到使用Werkzeug调试控制台,我的其他参数 在此范围内定义。如何定义一个参数,而另一个参数(由装饰器函数接收)在程序流程的同一点是否未定义?我想也许这是一个怪癖只会影响默认值的参数,所以我把它切换到一个必需的参数并手动传入None
,但这仍然产生了错误?
当其他参数在范围内时,为什么user
超出范围?我该如何修复这个装饰器?
答案 0 :(得分:3)
您正在内部函数中导入user
:
from flast.ext.login import current_user as user
这使得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
或者可能将外部user
命名为default_user
或类似。
现在user
永远不会在内部函数中赋值,并且仍然是对外部作用域的非本地引用。