用藍圖實現模塊化應用

Flask 使用了 藍圖 的概念在一個應用或者跨應用中構建應用組件以及支持通用模式。 藍圖很好地簡化了大型應用工做的方式,並提供給 Flask 擴展在應用上註冊操做的核心方法。 一個 Blueprint 對象與 Flask 應用對象的工做方式很像,但它確實不是一個應用, 而是一個描述如何構建或擴展應用的 藍圖 。css

爲何用藍圖?

Flask中的藍圖旨在針對這些狀況:html

  • 把一個應用分解成一系列的藍圖。對於大型的應用是理想化的;一個項目能實例化一個應用, 初始化一些擴展,以及註冊一系列的藍圖。
  • 以一個 URL 前綴和/或子域在一個應用上註冊藍圖。 URL 前綴/子域名中的參數即成爲這個藍圖下的全部視圖函數的共同的視圖參數(默認狀況下)。
  • 在一個應用中用不一樣的 URL 規則屢次註冊一個藍圖。
  • 經過藍圖提供模板過濾器、靜態文件、模板和其它功能。一個藍圖不必定要實現應用或視圖函數。
  • 初始化一個 Flask 擴展時,在這些狀況中註冊藍圖。

Flask 中的藍圖不是即插應用,由於它實際上並非一個應用 – 它是能夠註冊,甚至能夠屢次註冊到應用上的操做集合。爲何不使用多個應用對象?你能夠作到那樣 (見 應用調度 ),可是你的應用會有分開的配置,並在 WSGI 層管理。python

藍圖做爲 Flask 層提供分割的替代,共享應用配置,而且能夠更改所註冊的應用對象。其短板是你不能在應用建立後撤銷註冊一個藍圖而不銷燬整個應用對象。web

藍圖的概念

藍圖的基本設想是它們記錄註冊到一個應用時的操做執行狀況。 當從一個端點到另外一端分發請求和生成 URL 時,Flask 關聯視圖函數和藍圖。flask

第一個藍圖

這看起來像是一個很是基本的藍圖。在這個案例中,咱們想要實現一個簡單渲染靜態模板的藍圖:app

from flask import Blueprint, render_template, abort from jinja2 import TemplateNotFound simple_page = Blueprint('simple_page', __name__, template_folder='templates') @simple_page.route('/', defaults={'page': 'index'}) @simple_page.route('/<page>') def show(page): try: return render_template('pages/%s.html' % page) except TemplateNotFound: abort(404) 

當咱們使用 \@simple_page.route 裝飾器綁定函數時,藍圖會記錄下所登記的 show 函數。當之後在應用中註冊藍圖時,這個函數會被註冊到應用中。此外,它會給函數名加上由 Blueprint 的構造函數中給出的藍圖的名稱做爲前綴 (在此例中是 simple_page)。函數

註冊藍圖

如何註冊藍圖了?像這樣:url

from flask import Flask from yourapplication.simple_page import simple_page app = Flask(__name__) app.register_blueprint(simple_page) 

若是你檢查註冊到應用的規則,你將會發現這些:spa

[<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
 <Rule '/<page>' (HEAD, OPTIONS, GET) -> simple_page.show>,
 <Rule '/' (HEAD, OPTIONS, GET) -> simple_page.show>]

第一個顯然是來自應用自身,用於靜態文件。其它的兩個用於 simple_page 藍圖中的 show 函數。如你所見,它們的前綴是藍圖的名稱,而且用一個點(.)來分割。code

不過,藍圖也能夠在不一樣的位置掛載:

app.register_blueprint(simple_page, url_prefix='/pages') 

果真,生成這些規則:

[<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
 <Rule '/pages/<page>' (HEAD, OPTIONS, GET) -> simple_page.show>,
 <Rule '/pages/' (HEAD, OPTIONS, GET) -> simple_page.show>]

總之,你能夠屢次註冊藍圖,可是不必定每一個藍圖都能正確響應。 是否可以屢次註冊實際上取決於你的藍圖是如何編寫的,是否能根據不一樣的位置作出正確的響應。

藍圖資源

藍圖也能夠提供資源。有時候你會只爲它提供的資源而引入一個藍圖。

藍圖資源文件夾

與常規應用同樣,藍圖被認爲是包含在一個文件夾中。雖然多個藍圖能夠源自相同的文件夾中, 它並沒必要須是這種狀況而且一般不建議這樣作。

這個文件夾會從 Blueprint 的第二個參數中推斷出來,一般是 __name__ 。 這個參數決定對應藍圖的是哪一個邏輯的 Python 模塊或包。若是它指向一個存在的 Python 包,這個包(一般是文件系統中的文件夾)就是資源文件夾。若是是一個模塊, 模塊所在的包就是資源文件夾。你能夠訪問 Blueprint.root_path 屬性來查看資源文件夾什麼:

>>> simple_page.root_path '/Users/username/TestProject/yourapplication' 

你能夠使用 open_resource() 函數快速性這個文件夾中打開資源:

with simple_page.open_resource('static/style.css') as f: code = f.read() 

靜態文件

一個藍圖能夠經過 static_folder 關鍵字參數提供一個指向文件系統上文件夾的路 徑,來公開一個帶有靜態文件的文件夾。這能夠是一個絕對路徑,也能夠是相對於藍圖文件夾的路徑:

admin = Blueprint('admin', __name__, static_folder='static') 

默認狀況下,路徑最右邊的部分就是它在 web 上所公開的地址。由於這裏這個文件夾叫作 static , 它會在藍圖 + /static 的位置上可用。也就是說,藍圖爲 /admin 把靜態文件夾註冊到 /admin/static 。

最後是命名的 blueprint_name.static ,這樣你能夠生成它的 URL ,就像你對應用的靜態文件夾所作的那樣:

url_for('admin.static', filename='style.css') 

模板

若是你想要藍圖公開模板,你能夠提供 Blueprint 構造函數中的 template_folder 參數來實現:

admin = Blueprint('admin', __name__, template_folder='templates') 

像對待靜態文件同樣,路徑能夠是絕對的或是相對藍圖資源文件夾的。模板文件夾會 被加入到模板的搜索路徑中,可是比實際的應用模板文件夾優先級低。 這樣,你能夠容易地在實際的應用中覆蓋藍圖提供的模板。

那麼當你有一個 yourapplication/admin 文件夾中的藍圖而且你想要渲染 'admin/index.html' 模板, 且你已經提供了 templates 做爲 template_folder ,你須要這樣建立文件: yourapplication/admin/templates/admin/index.html

構建 URLs

當你想要從一個頁面連接到另外一個頁面,你能夠像一般一個樣使用 url_for() 函數,只是你要在 URL 的末端加上藍圖的名稱和一個點(.)做爲前綴:

url_for('admin.index') 

此外,若是你在一個藍圖的視圖函數或是模板中想要從連接到同一藍圖下另外一個端點, 你能夠經過對端點的只加上一個點做爲前綴來使用相對的重定向:

url_for('.index') 

這個案例中,它實際上連接到 admin.index ,假如請求被分派到任何其它的 admin 藍圖端點。

相關文章
相關標籤/搜索