[英]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.