这里的问题是,decorator()
您返回的函数与正在修饰的函数的名称不同,因此URL构建器找不到您的index
视图。您需要使用模块中的wraps()
装饰器functools
来复制原始函数的名称。另一个问题(您仍然必须遇到)是您不接受装饰器中的参数并将其传递给原始函数。这是更正的装饰器:
from functools import wraps
def logged_in(fn):
@wraps(fn)
def decorator(*args, **kwargs):
if 'email' in session:
return fn(*args, **kwargs)
else:
# IMO it's nicer to abort here and handle it in errorhandler.
abort(401)
return decorator
更多解释 :在Python装饰器中,是一个函数,该函数将另一个函数作为其参数并返回一个函数作为其结果。所以以下
@logged_in
def index(): pass
基本上与
def index(): pass
index = logged_in(index)
在这种情况下,问题在于logged_in
装饰器返回的不是原始函数,而是包装原始函数的包装器(decorator
在代码中称为)。该包装器的名称(decorator
)与要包装的原始函数不同。现在app.route()
,您将在之后调用的decoratorlogged_in
看到此新函数,并使用其名称(decorator
)为其注册路由。问题就出在这里:您希望修饰后的函数具有相同的名称(index
),因此可用于url_for()
为其获取路线。这就是为什么您需要手动复制名称的原因
decorator.__name__ = fn.__name__
或更好地使用模块中的帮助update_wrapper
和wraps
帮助functools
,为您做的甚至更多。