如何检查 Python 中的函数装饰器

How to check function decorators in Python

我正在使用(很棒的)Flask framework in which some of the routes are protected by a flask-login @login_required 装饰器构建一个网站,如下所示:

@app.route('/awesomepage')
@login_required  # <-- this is what I mean
def awesome_page():
    return render_template('awesome.html')

当有人注销时,他通常会被重定向到他按下注销时正在查看的页面。但是当一个人从他需要登录的页面注销时(即具有 @login_required 装饰器),他在注销后会收到 401 Unauthorized 错误。因此,当将用户重定向回原始页面时,我想检查他们来自的页面是否有 @login_required 装饰器,如果有,则将他们重定向到首页。

我当前的注销视图如下所示:

@app.route('/logout')
def logout():
    logout_user()
    next_url = request.args.get('next') or request.referrer or url_for('index')
    return redirect(next_url)

所以在这段代码中我想检查 request.referrer 是否有一个 @login_required 装饰器。有人知道我该怎么做吗?欢迎所有提示!

你不能,不容易。

更好的选择是通过在模板中明确设置 login_required 标志,告诉页面在注销 link 中包含更好的 next 值:

@app.route('/awesomepage')
@login_required
def awesome_page():
    return render_template('awesome.html', login_required=True)

并使用以下方式呈现注销 link:

{% if login_required %}{{ url_for('logout', next=url_for('index')) }}
{% else %}{{ url_for('logout' }}{% endif %}

另一种方法是定义登录视图,然后 login_required 重定向到该视图。 可能 成为您的索引页。

另一种方法是创建一个增强的 login_required 装饰器,设置一个全局变量,然后测试:

from functools import wraps

from flask import g
from flask_login import login_required

def my_login_required(f):
    @login_required
    @wraps(f)
    def wrapped(*args, **kwargs):
        g.login_required = True
        return f(*args, **kwargs)
    return wrapped

然后在您的视图上使用该装饰器而不是 Flask-Login 版本:

@app.route('/awesomepage')
@my_login_required
def awesome_page():
    return render_template('awesome.html')

并更新模板以查找全局:

{% if g.login_required %}{{ url_for('logout', next=url_for('index')) }}
{% else %}{{ url_for('logout' }}{% endif %}