flask login_required 装饰器位置 - 从头开始​​编写

Posted

技术标签:

【中文标题】flask login_required 装饰器位置 - 从头开始​​编写【英文标题】:flask login_required decorator location - written from scratch 【发布时间】:2020-10-18 21:27:27 【问题描述】:

不久前我开始尝试使用烧瓶,我非常喜欢可以在需要时扩展的简约框架的想法。我对 Web 框架的经验有限,但我确实了解框架的概念。我遇到了以下问题(值得一提的是,我确实想要使用flask-login,我正在尝试从我的工作php系统复制登录系统):

我使用应用工厂创建了一个新应用,在此过程中加载了 2 个蓝图。一个是身份验证(登录/注销),一个是仪表板(索引、主页面、默认页面,无论你想怎么称呼它)。登录就像一个魅力,它正是它应该做的。我需要做的就是编写一个 login_required 装饰器并将它包裹在我只想登录的路由周围。

这是我的代码,但当我尝试在其中一个蓝图中运行它时,我收到了以下消息:

AttributeError: 'Flask' object has no attribute 'login_required'

我应该将装饰器放在哪里,以使其被识别为“全局”组件并可以从任何地方访问,主要是从蓝图?

初始化.py

from flask import Flask

def init():
    app = Flask(__name__, instance_relative_config=False)

    app.config.from_object('config.Config')

    def login_required(f):
        @wraps(f)
        def wrap(*args, **kwargs):
            if 'auth' in session:
                return f(*args, **kwargs)
            else:
                flash('You need to login first')
                return redirect(url_for('auth.login'))

        return wrap

    with app.app_context():
        from application.auth import auth
        from application.dashboard import dashboard
    
        app.register_blueprint(auth.bp_auth)
        app.register_blueprint(dashboard.bp_dashboard)
    
        return app

dashboard.py(这是蓝图之一)

from flask import Blueprint, current_app, redirect, render_template, session, url_for

bp_dashboard = Blueprint('dashboard', __name__)

@bp_dashboard.route('/')
@current_app.login_required # I also tried @app.login_required, @login_required, same error
def index():    
    return render_template('dashboard/index.html')

我做错了什么?我想我对整个应用程序上下文概念还是很陌生,但我认为 current_app 可以解决这个问题。

【问题讨论】:

【参考方案1】:

根据您上面的代码,我猜您缺少from functools import wraps

参考这个https://docs.python.org/3/library/functools.html#functools.wraps

为了使事情更加一致,只需将下面的块移动到auth Blueprint

from functools import wraps  # Don't forget this import
[..]

def login_required(f):
    @wraps(f)
    def wrap(*args, **kwargs):
        if 'auth' in session:
            return f(*args, **kwargs)
        else:
            flash('You need to login first')
            return redirect(url_for('auth.login'))

    return wrap

然后在dashboard Blueprint 中导入它

from flask import Blueprint, current_app, redirect, render_template, session, url_for

from .auth import login_required # here

bp_dashboard = Blueprint('dashboard', __name__)

@bp_dashboard.route('/')
@login_required  # You don't need to prefix it with "bp_dashboard" nor  "current_app"
def index():    
    return render_template('dashboard/index.html')

希望这能解决您的问题。

【讨论】:

以上是关于flask login_required 装饰器位置 - 从头开始​​编写的主要内容,如果未能解决你的问题,请参考以下文章

装饰器的顺序在 Flask 视图中是不是重要?

Flask:一次装饰每条路线?

装饰 login_required Django 装饰器

如何使用 Flask-Login 保护 Flask-App 中的 Dash-Apps?

装饰器login_required

Django:调整@login_required 装饰器