flask-自定义扩展
简介
使用场景:有很多蓝图,其中只有account蓝图不需要做登录验证,其他视图都要做登录验证,一般有两个办法:
1.在每一个需要做验证的蓝图中加上before_request装饰器函数(太麻烦)
@home.before_request
def bf():
user_dict = session.get('user_info')
if not user_dict:
return redirect('/login')
2.在全局做配置
from flask import Flask, current_app
from flask_sqlalchemy import SQLAlchemy
from flask_session import Session
# 包含了SQLALchemy的所有操作
db = SQLAlchemy()
auth = Auth()
def check_login():
user_dict = session.get('user_info') if not user_dict: return redirect('/login')
def create_app():
app = Flask(__name__)
app.debug = True
app.config.from_object('settings.DevelopmentConfig')
from .views import account
from .views import home
app.register_blueprint(account.ac)
app.register_blueprint(home.home)
Session(app)
db.init_app(app)
app.before_request(check_login)
return app
## 可以这么做,但是不太符合flask开发规范。修改一下,效果sqlalchemy一样,通过一个init_app的函数来做。
引入Auth类
from flask import redirect, session, request
class Auth:
def __init__(self, app=None):
self.app = app
if app:
self.init_app(app)
def init_app(self, app):
app.auth_manager = self # 把当前app赋值给auth_manager
self.app = app
app.before_request(self.check_login)
app.context_processor(self.context_processor) # 我们的定义变量在所有模板中可见
def check_login(self):
if request.path in ['/login', '/register']:
return
user = session.get('user_info')
if not user:
return redirect('/login')
def context_processor(self):
user = session.get('user_info')
return dict(current_user=user)
def login(self, data):
session['user_info'] = data
def logout(self):
"""
将用户登录信息,放入session
:param data:
:return:
"""
del session['user_info']
这样,在返回app前,就通过auth.iinit_app(app)就可以达到全局的效果,并且可以过滤其他URL。
from flask import Flask, current_app from flask_sqlalchemy import SQLAlchemy from flask_session import Session from exts.auth import Auth # 包含了SQLALchemy的所有操作 db = SQLAlchemy() auth = Auth() def create_app(): app = Flask(__name__) app.debug = True app.config.from_object('settings.DevelopmentConfig') from .views import account from .views import home app.register_blueprint(account.ac) app.register_blueprint(home.home) Session(app) db.init_app(app) auth.init_app(app) return app
把认证相关的功能放在一个类中,用户登录注销通过current_app直接调用相关功能。
@ac.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'GET': form = LoginForm() return render_template('login.html', form=form) form = LoginForm(formdata=request.form) if not form.validate(): return render_template('login.html', form=form) user = request.form.get('user') pwd = request.form.get('pwd') user_obj = db.session.query(models.Users).filter(models.Users.name == user, models.Users.pwd == pwd).first() db.session.remove() if not user_obj: return render_template('login.html', msg='用户名或密码错误!', form=form) uid = str(uuid4()) current_app.auth_manager.login({'id': uid, 'user': user_obj.name}) return redirect('/index')