1. 程式人生 > >flask藍圖

flask藍圖

flask 藍圖

**藍圖(blueprint)**是一種組織一種相關檢視和其他程式碼的方法(分層解耦) flask中有兩個藍圖,一個用於身份驗證,另一個用於部落格帖子功能。每個藍圖的程式碼都將在一個單獨的模組中 身份驗證

建立一個名為auth的藍圖,__name__定義位置,url_prefix關聯url
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')
從工廠匯入並註冊藍圖 app.register_blueprint()
def create_app():
    app = ...
    # existing code omitted

    from . import auth
    app.register_blueprint(auth.bp)

    return app

第一個檢視:

@bp.route('/register', methods=('GET', 'POST'))
#@bp.route將URL /register 與register檢視功能相關聯。
#當Flask收到請求時/auth/register,它將呼叫register檢視並使用返回值作為響應。
def register():
#如果使用者提交了表格, request.method將會是'POST'。在這種情況下,請開始驗證輸入。
    if request.method == 'POST':
	#request.form是一種特殊型別的 dict對映,提供表單鍵和值。使用者將輸入他們的username和password。
        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.' elif db.execute( 'SELECT id FROM user WHERE username = ?', (username,) ).fetchone() is not None: error = 'User {} is already registered.'.format(username) if error is None: db.execute( 'INSERT INTO user (username, password) VALUES (?, ?)', (username, generate_password_hash(password)) ) db.commit() return redirect(url_for('auth.login')) flash(error) #驗證失敗 return render_template('auth/register.html')

當用戶訪問該 /auth/register URL時,該register檢視將返回帶有表單的HTML以供他們填寫。當他們提交表單時,它將驗證他們的輸入並再次顯示錶單並顯示錯誤訊息或建立新使用者並轉到登入頁面。

@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'))
#session是一種dict跨請求儲存資料的。
#驗證成功後,使用者id將儲存在新會話中。
#資料儲存在傳送到瀏覽器的cookie中,然後瀏覽器將其與後續請求一起發回。
#Flask安全地對資料進行簽名,以便不會被篡改
        flash(error)

    return render_template('auth/login.html')
@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()

退出

@bp.route('/logout')
def logout():
    session.clear()
    return redirect(url_for('index'))

其他檢視認證

建立,編輯和刪除部落格帖子將需要使用者登入。可以使用裝飾器為其應用的每個檢視進行檢查。

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

這個裝飾器返回一個新的檢視函式,它包裝了它應用的原始檢視。新函式檢查使用者是否已載入,否則重定向到登入頁面。如果載入了使用者,則呼叫原始檢視並繼續正常。在編寫部落格檢視時,您將使用此裝飾器。

端點和URLs(Endpoints and URLs)

使用藍圖時,藍圖的名稱將附加到函式的名稱前面,因此login您在上面編寫的函式的端點是’auth.login’因為您將其新增到’auth’ 藍圖中。