本文转载自微信公众号「dongfanger」,作者:dongfanger。转载本文请联系东方儿公众号。Flask的视图函数用于响应请求。单个URL可以匹配单个View,那么有没有更优雅的方式来写多个类似的URL,比如:/auth/register/auth/login/auth/logout?BlueprintsBlueprints是一个路由组,可以把常用的路由前缀注册为一个Blueprint,例如:首先在flaskr/auth.py文件中定义一个Blueprint:importfunctoolsfromflaskiimport(Blueprint,flash,g,redirect,render_template,request,session,url_for)fromwerkzeug.securityimportcheck_password_hash,generate_password_hashfromflaskr.dbimportget_dbbputh=Blueprint('auth',__name__,url_prefix='/auth')'auth'是蓝图的名称。__name__用于告诉Blueprint它的定义位置。url_prefix是路由前缀。然后在flaskr/__init__.py文件中注册:defcreate_app():app=...#existingcodeomittedfrom.importauthapp.register_blueprint(auth.bp)returnappViews定义并注册Blueprints后,就可以在视图中使用了。例如:①在flaskr/auth.py文件中添加注册视图:@bp.route('/register',methods=('GET','POST'))defregister():ifrequest.method=='POST':username=request.form['username']password=request.form['password']db=get_db()error=Noneifnotusername:error='Usernameisrequired.'elifnotpassword:error='Passwordisrequired.'iferrorisNone:try:db.execute("INSERTINTOuser(username,password)VALUES(?,?)",(username,generate_password_hash(password)),)db.commit()exceptdb.IntegrityError:error=f"User{username}isalreadyregistered."else:returnredirect(url_for("auth.login"))flash(error)returnrender_template('auth/register.html')@bp.route会将路由前缀添加到'/register'形成/auth/register。request.form是一个字典,可以读取接口输入参数。db.execute执行SQL语句。db.commit()提交。redirect注册成功后重定向到登录页面。url_for根据视图名获取url,因为这里使用了Blueprint,所以入参为“auth.login”。如果不使用Blueprint,只需将视图函数的名称写为url_for()函数的参数即可。②在flaskr/auth.py文件中添加登录视图:@bp.route('/login',methods=('GET','POST'))deflogin():ifrequest.method=='POST':username=request.form['username']password=request.form['password']db=get_db()error=Noneuser=db.execute('SELECT*FROMuserWHEREusername=?',(username,)).fetchone()ifuserisNone:error='Incorrectusername.'elifnotcheck_password_hash(user['password'],password):error='Incorrectpassword.'iferrorisNone:session.clear()session['user_id']=user['id']returnredirect(url_for('索引'))flash(error)returnrender_template('auth/login.html')fetchone()取一行数据,fetchall()取多行数据。登录成功后会把user_id存入session中,session是一个字典,这样在后续的请求中就可以使用到这个数据。例如:@bp.before_app_requestdefload_logged_in_user():user_id=session.get('user_id')ifuser_idisNone:g.user=Noneelse:g.user=get_db().execute('SELECT*FROMuserWHEREid=?',(user_id,)).fetchone()值得注意的是@bp.before_app_request有点像setup,就是在所有请求之前运行这段代码。③在flaskr/auth.py文件中添加注销视图:flaskr/auth.py@bp.route('/logout')deflogout():session.clear()returnredirect(url_for('index'))session。clear()清除会话。④最后可以在flaskr/auth.py文件中写一个装饰器进行鉴权:deflogin_required(view):@functools.wraps(view)defwrapped_view(**kwargs):ifg.userisNone:returnredirect(url_for('auth.login'))returnview(**kwargs)returnwrapped_view这个login_required装饰器可以加到需要登录才能访问的view上。参考资料:https://flask.palletsprojects.com/en/2.0.x/tutorial/views/
