【发布时间】:2018-05-08 03:17:44
【问题描述】:
说,我有一个手工制作的@login-required装饰器:
from functools import wraps
def login_required(decorated_function):
"""Decorator to check if user is logged in."""
@wraps(decorated_function)
def wrapper(*args, **kwargs):
if False: # just to check it's working
return decorated_function(*args, **kwargs)
else:
flash('You need to login, to access this page')
return redirect(url_for('login'))
return wrapper
还有一个函数,用@app.route() 和@login_required 装饰(为简洁起见省略了login 的端点):
@app.route('/')
@login_required
def index():
return "Hello!"
现在,如果我按预期尝试访问/,它不会让我访问,而是会重定向到登录页面。
不过,如果我滑动装饰器的顺序,即:
@login_required
@app.route('/')
def index():
return "Hello!"
然后我可以访问/,尽管我不应该这样做。
我知道Flask documentation on the subject 表示:
在应用更多装饰器时,请始终记住 route() 装饰器位于最外层。
我好奇的不是正确的方法是什么(@app.route() 装饰器必须在最外面 - 明白了),而是为什么它会这样工作(即什么是它背后的机制)。
我看了@app.route()source code:
def route(self, rule, **options):
def decorator(f):
endpoint = options.pop('endpoint', None)
self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator
This answer,或多或少帮助我理解了装饰器的机制。不过,我之前从未见过函数刚刚返回(没有调用它),所以我自己做了一个小实验(结果证明是可行的,当然):
def my_decorator():
def decorator (function):
return function
return decorator
@my_decorator()
def test():
print('Hi')
test()
所以,我想了解一下:
- 为什么装饰器的顺序在上面的确切情况下以及
@app.route()和其他装饰器的一般情况下很重要(我猜这是相同的答案)?让我感到困惑的是,@app.route()只是将 url 规则添加到应用程序(即self.add_url_rule(rule, endpoint, f, **options)并返回函数,仅此而已,那么为什么顺序很重要? -
@app.route()是否会覆盖它上面的所有装饰器(如果是这样的话)?
我也是aware,装饰器的应用顺序是从下到上的,虽然对我来说并没有让事情变得更清楚。我错过了什么?
【问题讨论】:
标签: python flask decorator python-decorators