Flask 的 Blueprints 和 Views

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

[[437021]]

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

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

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

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

Blueprints

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

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

import functools 
 
from flask import ( 
    Blueprint, flash, g, redirect, render_template, request, session, url_for 

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

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

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

Views

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

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

@bp.route('/register', methods=('GET''POST')) 
def register(): 
    if request.method == 'POST'
        username = request.form['username'
        password = request.form['password'
        db = get_db() 
        error = None 
 
        if not username: 
            error = 'Username is required.' 
        elif not password
            error = 'Password is required.' 
 
        if error is None: 
            try: 
                db.execute
                    "INSERT INTO user (username, password) VALUES (?, ?)"
                    (username, generate_password_hash(password)), 
                ) 
                db.commit() 
            except db.IntegrityError: 
                error = f"User {username} is already registered." 
            else
                return redirect(url_for("auth.login")) 
 
        flash(error) 
 
    return render_template('auth/register.html'
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • @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:

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

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

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

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

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

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

在需要登录才能访问的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技术栈公众号