Flask 的 Blueprints 和 Views

开发 前端
url_for根据view名字来获取url,因为这里用到了Blueprint,所以入参是"auth.login"。如果没有用Blueprint,url_for()函数入参就写view函数名即可。

[[437021]]

本文转载自微信公众号「dongfanger」,作者dongfanger。转载本文请联系dongfanger公众号。

 Flask的view函数是用来对请求作出响应的。单个URL能匹配到单个View,那么多个类似的URL,比如:

  1. /auth/register 
  2. /auth/login 
  3. /auth/logout 

有没有什么比较优雅的写法呢?

Blueprints

Blueprints就是一个路由分组,可以把共同的路由前缀注册为一个Blueprint,比如:

在flaskr/auth.py文件中先定义一个Blueprint:

  1. import functools 
  2.  
  3. from flask import ( 
  4.     Blueprint, flash, g, redirect, render_template, request, session, url_for 
  5. from werkzeug.security import check_password_hash, generate_password_hash 
  6.  
  7. from flaskr.db import get_db 
  8.  
  9. bp = Blueprint('auth', __name__, url_prefix='/auth'
  • 'auth'是Blueprint的名字。
  • __name__用来告诉Blueprint它的定义位置。
  • url_prefix就是路由前缀。

接着在flaskr/__init__.py文件中注册:

  1. def create_app(): 
  2.     app = ... 
  3.     # existing code omitted 
  4.  
  5.     from . import auth 
  6.     app.register_blueprint(auth.bp) 
  7.  
  8.     return app 

Views

定义和注册了Blueprints后就可以在view中使用了。比如:

①在flaskr/auth.py文件中添加一个注册view:

  1. @bp.route('/register', methods=('GET''POST')) 
  2. def register(): 
  3.     if request.method == 'POST'
  4.         username = request.form['username'
  5.         password = request.form['password'
  6.         db = get_db() 
  7.         error = None 
  8.  
  9.         if not username: 
  10.             error = 'Username is required.' 
  11.         elif not password
  12.             error = 'Password is required.' 
  13.  
  14.         if error is None: 
  15.             try: 
  16.                 db.execute
  17.                     "INSERT INTO user (username, password) VALUES (?, ?)"
  18.                     (username, generate_password_hash(password)), 
  19.                 ) 
  20.                 db.commit() 
  21.             except db.IntegrityError: 
  22.                 error = f"User {username} is already registered." 
  23.             else
  24.                 return redirect(url_for("auth.login")) 
  25.  
  26.         flash(error) 
  27.  
  28.     return render_template('auth/register.html'
  • @bp.route就会把路由前缀加到'/register'上拼成/auth/register。
  • request.form是一个字典,可以读取接口入参。
  • db.execute执行SQL语句。db.commit()提交。
  • redirect在注册成功后重定向到登录页面。
  • url_for根据view名字来获取url,因为这里用到了Blueprint,所以入参是"auth.login"。如果没有用Blueprint,url_for()函数入参就写view函数名即可。

②在flaskr/auth.py文件中添加一个登录view:

  1. @bp.route('/login', methods=('GET''POST')) 
  2. def login(): 
  3.     if request.method == 'POST'
  4.         username = request.form['username'
  5.         password = request.form['password'
  6.         db = get_db() 
  7.         error = None 
  8.         user = db.execute
  9.             'SELECT * FROM user WHERE username = ?', (username,) 
  10.         ).fetchone() 
  11.  
  12.         if user is None: 
  13.             error = 'Incorrect username.' 
  14.         elif not check_password_hash(user['password'], password): 
  15.             error = 'Incorrect password.' 
  16.  
  17.         if error is None: 
  18.             session.clear() 
  19.             session['user_id'] = user['id'
  20.             return redirect(url_for('index')) 
  21.  
  22.         flash(error) 
  23.  
  24.     return render_template('auth/login.html'
  • fetchone()取一行数据,fetchall()取多行数据。
  • 登录成功后会把user_id存入session中,session是一个字典,这样后续请求就可以用到这个数据。比如:
  1. @bp.before_app_request 
  2. def load_logged_in_user(): 
  3.     user_id = session.get('user_id'
  4.  
  5.     if user_id is None: 
  6.         g.user = None 
  7.     else
  8.         g.user = get_db().execute
  9.             'SELECT * FROM user WHERE id = ?', (user_id,) 
  10.         ).fetchone() 

值得注意的是@bp.before_app_request有点像setup,就是在所有请求前先运行这一段代码。

③在flaskr/auth.py文件中添加一个登出view:

  1. flaskr/auth.py 
  2. @bp.route('/logout'
  3. def logout(): 
  4.     session.clear() 
  5.     return redirect(url_for('index')) 
  • session.clear()清除session。

④最后可以在在flaskr/auth.py文件中顺手写一个装饰器,用来做认证鉴权:

  1. def login_required(view): 
  2.     @functools.wraps(view
  3.     def wrapped_view(**kwargs): 
  4.         if g.user is None: 
  5.             return redirect(url_for('auth.login')) 
  6.  
  7.         return view(**kwargs) 
  8.  
  9.     return wrapped_view 

在需要登录才能访问的view上,就可以加上这个login_required装饰器。

参考资料:

https://flask.palletsprojects.com/en/2.0.x/tutorial/views/

 

责任编辑:武晓燕 来源: dongfanger
相关推荐

2022-05-30 06:30:20

查询MySQL数据库

2012-06-07 09:21:55

ibmdw

2015-07-30 09:49:33

Table ViewsTips加速

2015-07-29 10:11:18

Tableviews加速开发

2023-06-07 08:18:25

2023-03-27 15:07:27

PythonWeb 开发编程语言

2022-03-28 18:59:02

DockerFlask深度学习

2023-08-27 15:10:29

Django和Flask框架

2024-09-29 10:34:31

FlaskPythonAPI

2016-11-08 10:24:37

FlaskPython插件

2019-05-15 13:48:17

PythonDjangoFlask

2023-06-08 08:13:43

2023-06-30 08:54:39

2021-08-19 07:25:02

数据库Flask插件

2023-10-09 18:17:52

Python语言Web

2017-05-11 14:00:02

Flask请求上下文应用上下文

2023-06-28 08:08:06

Flask上下文生命周期

2022-02-16 07:47:48

flask分页SQLAlchemy

2022-06-21 09:27:01

PythonFlaskREST API

2022-08-31 15:09:03

PythonOthers
点赞
收藏

51CTO技术栈公众号