Flask - 藍圖的基本使用

一、前言

參考https://www.cnblogs.com/poloyy/p/15004389.html

  • 在前面的例子中,所有的頁面處理邏輯都是放在同一個文件中,隨着業務代碼的增加,將所有代碼都放在單個程序文件中是非常不合適的
  • 不僅會讓閱讀代碼變得困難,而且會給後期維護帶來麻煩
  • Flask 中使用藍圖,提供了模塊化管理程序路由的功能,使程序結構更加清晰

二、藍圖簡介

  • 隨着 Flask 程序越來越複雜,需要對程序進行模塊化的處理
  • 藍圖 (Blueprint) 是 Flask 程序的模塊化處理機制
  • 它是一個存儲視圖方法的集合
  • Flask 程序通過 Blueprint 來組織 URL 以及處理請求

1、 Blueprint 具有以下屬性

  • 一個項目可以具有多個 Blueprint
  • Blueprint 可以單獨擁有自己的模板、靜態文件的目錄
  • 在應用初始化時,註冊需要使用的 Blueprint

2、基本用法

功能概述:假設網站包含有如下 4 個頁面

  • 前兩個都是 /news 前綴,可以組成一個藍圖 news
  • 後兩個是 /products 前綴,可以組成一個藍圖 products
  • 相當於四個視圖函數,兩個藍圖

使用藍圖後,路由匹配流程

  1. 瀏覽器訪問路徑 /products/car
  2. Flask 框架在藍圖 news 和藍圖 products 中查找匹配該頁面路徑的路由
  3. 發現在藍圖 products 中,存在和路徑 /products/car 匹配的視圖函數 car_products
  4. 最後將請求轉發給函數 car_products 處理

三、實戰

1、目錄結構

例子程序包括 2 個藍圖,由 3 個文件構成:

  • practice.py,程序的主文件;
  • news.py,實現藍圖 news;
  • products.py,實現藍圖 products。

2、practice.py

from flask import Flask, Blueprint
# 導入藍圖類
from blueprints import news,products

app = Flask(__name__)

# 註冊藍圖
app.register_blueprint(news.blueprint)
app.register_blueprint(products.blueprint)

if __name__ == '__main__':
    app.run(debug=True)

3、news.py

頁面的絕對路徑是 /news/society/ 和 /news/tech/,因爲藍圖的 url_prefix 設置爲 news,在藍圖內部,頁面的相對路徑是 /society/ 和 /tech/

from flask import Blueprint

"""
實例化藍圖對象
第一個參數:藍圖名稱
第二個參數:導入藍圖的名稱
第三個參數:藍圖前綴,該藍圖下的路由規則前綴都需要加上這個
"""

blueprint = Blueprint('news',__name__,url_prefix="/news")

# 用藍圖註冊路由
@blueprint.route("/society/")
def society_news():
    return "社會新聞版塊"

@blueprint.route("/tech/")
def tech_news():
    return "新聞版塊"

4、products.py

頁面的絕對路徑是 /products/car/ 和 /product/baby/,因爲藍圖的 url_prefix 等於 products,在藍圖內部,頁面的相對路徑是 /car/ 和 /baby/

from flask import Blueprint

blueprint = Blueprint("products", __name__, url_prefix="/product")


@blueprint.route("/car")
def car_products():
    return "汽車產品版塊"


@blueprint.route("/baby")
def baby_products():
    return "嬰兒產品版塊"

5、請求結果

 四、更具擴展性的架構

概述

隨着業務代碼的增加,需要爲 Flask 程序提供一個具備擴展性的架構,根據 Flask 程序的擴展性分爲如下三種類型:

1、所有的頁面邏輯放在同一個文件中

在這種架構中,程序完全不具備擴展性

在初學 Flask 時,使用的栗子都是這種類型

2、使用一個獨立的 Python 文件實現藍圖

在這種架構中,程序具備一定的擴展性:

  • 程序由主程序和多個藍圖構成
  • 每個藍圖對應一個 Python 文件
  • 所有的藍圖共享相同的模板文件目錄
  • 所有的藍圖共享相同的靜態文件目錄

上面的栗子就是採用這種架構

程序包含 2 個藍圖: news 和 products,由 3 個文件構成:practice.pynews.pyproducts.py,其中 news.py 實現新聞版塊,products.py 實現產品版塊

3、使用一個獨立的目錄實現藍圖

在這種架構中,程序的擴展性最好:

  • 程序由主程序和多個藍圖構成
  • 每個藍圖對應一個獨立的目錄,存儲與這個藍圖相關的文件
  • 每個藍圖有一個獨立的模板文件目錄
  • 每個藍圖有一個獨立的靜態文件目錄

模板文件尋找規則

每個藍圖可以擁有獨立的模板文件目錄,模板文件尋找規則如下:

  • 如果項目中的 templates 文件夾中存在相應的模板文件,則使用 templates 文件夾下的模板文件;
  • 如果項目中的 templates 文件夾中沒有相應的模板文件,則使用定義藍圖的時候指定的 templates 文件夾下的模板文件
  • 項目中的 templates 文件夾優先級大於指定的 templates 文件夾

靜態文件尋找規則

每個藍圖可以獨立的靜態文件目錄,靜態文件尋找規則如下:

  • 如果項目中的 static 文件夾中存在相應的靜態文件,則使用 static 文件夾下的靜態文件
  • 如果項目中的 static 文件夾中沒有相應的靜態文件,則使用定義藍圖的時候指定的 static 文件夾下的靜態文件
  • 項目中的 templates 文件夾優先級大於指定的 templates 文件夾

 五、擴展性實戰例子

1、目錄結構

2、目錄功能描述

3、 文件功能描述

4、app.py

from  flask import Flask
import news,products

app = Flask(__name__)

app.register_blueprint(news.blueprint)
app.register_blueprint(products.blueprint)

app.run(debug=True)

5、news/__init.py__

  • 藍圖中頁面的 URL 前綴爲 /news;
  • 藍圖的模板目錄爲 templates,絕對路徑爲 ‘項目目錄 /news/templates’;
  • 藍圖的靜態文件目錄爲 static,絕對路徑爲 ‘項目目錄 /news/static’
  • 調用 render_template (‘society.html’) 渲染模板文件 society.html,根據模板文件的查找規則,最終在 ‘項目目錄 /news/templates’ 目錄下找到模板文件
# 導入藍圖
from flask import Blueprint, render_template

"""
實例化藍圖對象
第一個參數:藍圖名稱
第二個參數:導入藍圖的名稱
第三個參數:藍圖前綴,該藍圖下的路由規則前綴都需要加上這個
"""
blueprint = Blueprint('news', __name__, url_prefix="/news", template_folder="templates", static_folder="static")


# 用藍圖註冊路由
@blueprint.route("/society/")
def society_news():
    return render_template('society.html')


@blueprint.route("/tech/")
def tech_news():
    return "IT 新聞板塊"

6、news/templates/society.html

 在模板文件中引用了靜態文件 news.css。{{url_for (‘news.static’,filename=‘news.css’) }} 的輸出爲 news/static/news.css,其中 news.static 表示藍圖 news 的 static 目錄

<link rel="stylesheet" href="{{ url_for('news.static',filename='news.css')}}">
<h1>社會新聞</h1>

7、news/static/news.css 

h1 {
    color: red;
}

8、product.py/__init.py__

from flask import Blueprint

blueprint = Blueprint('products', __name__, url_prefix='/products')

@blueprint.route("/car")
def car_products():
    return "汽車產品版塊"

@blueprint.route("/baby")
def baby_products():
    return "嬰兒產品版塊"

9、瀏覽器訪問效果

我的編輯好像沒升級,不支持部分css,本來社會新聞的標題應當是紅色的

 10、注意

  • 根據 templates、static 的查找規則,會優先查找項目根目錄的 templates、static 目錄下是否有對應的模板文件、靜態文件
  • 這裏 society.html 同時出現在根目錄的 templates 和藍圖目錄的 templates,應該優先返回根目錄的 templates 下的 society.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章