New in version 0.7.
為了在一個(gè)或多個(gè)應(yīng)用中,使應(yīng)用模塊化并且支持常用方案, Flask 引入了 藍(lán)圖 概念。藍(lán)圖可以極大地簡化大型應(yīng)用并為擴(kuò)展提供集中的注冊(cè)入口。
Blueprint 對(duì)象與 Flask 應(yīng)用對(duì)象的工作方式類似,但不是一個(gè)真正 的應(yīng)用。它更像一個(gè)用于構(gòu)建和擴(kuò)展應(yīng)用的 藍(lán)圖 。
Flask 中藍(lán)圖有以下用途:
Flask 中的藍(lán)圖不是一個(gè)可插撥的應(yīng)用,因?yàn)樗皇且粋€(gè)真正的應(yīng)用,而是一套可以注冊(cè) 在應(yīng)用中的操作,并且可以注冊(cè)多次。那么為什么不使用多個(gè)應(yīng)用對(duì)象呢?可以使用多個(gè) 應(yīng)用對(duì)象(參見應(yīng)用調(diào)度 ),但是這樣會(huì)導(dǎo)致每個(gè)應(yīng)用都使用自己獨(dú)立的配置,且只能在 WSGI 層中管理應(yīng)用。
而如果使用藍(lán)圖,那么應(yīng)用會(huì)在 Flask 層中進(jìn)行管理,共享配置,通過注冊(cè)按需改變應(yīng)用 對(duì)象。藍(lán)圖的缺點(diǎn)是一旦應(yīng)用被創(chuàng)建后,只有銷毀整個(gè)應(yīng)用對(duì)象才能注銷藍(lán)圖。
藍(lán)圖的基本概念是:在藍(lán)圖被注冊(cè)到應(yīng)用之后,所要執(zhí)行的操作的集合。當(dāng)分配請(qǐng)求時(shí), Flask 會(huì)把藍(lán)圖和視圖函數(shù)關(guān)聯(lián)起來,并生成兩個(gè)端點(diǎn)之前的 URL 。
以下是一個(gè)最基本的藍(lán)圖示例。在這里,我們將使用藍(lán)圖來簡單地渲染靜態(tài)模板:
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)
當(dāng)你使用 @simple_page.route 裝飾器綁定一個(gè)函數(shù)時(shí),藍(lán)圖會(huì)記錄下所登記的 show 函數(shù)。當(dāng)以后在應(yīng)用中注冊(cè)藍(lán)圖時(shí),這個(gè)函數(shù)會(huì)被注冊(cè)到應(yīng)用中。另外,它會(huì)把 構(gòu)建 Blueprint 時(shí)所使用的名稱(在本例為 simple_page )作為函數(shù)端點(diǎn) 的前綴。
可以這樣注冊(cè)藍(lán)圖:
from flask import Flask
from yourapplication.simple_page import simple_page
app = Flask(__name__)
app.register_blueprint(simple_page)
以下是注冊(cè)藍(lán)圖后形成的規(guī)則:
[<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
<Rule '/<page>' (HEAD, OPTIONS, GET) -> simple_page.show>,
<Rule '/' (HEAD, OPTIONS, GET) -> simple_page.show>]
第一條很明顯,是來自于應(yīng)用本身的用于靜態(tài)文件的。后面兩條是用于藍(lán)圖 simple_page 的 show 函數(shù)的。你可以看到,它們的前綴都是藍(lán)圖的名稱,并且使用一個(gè)點(diǎn)( . )來分隔。
藍(lán)圖還可以掛接到不同的位置:
app.register_blueprint(simple_page, url_prefix='/pages')
這樣就會(huì)形成如下規(guī)則:
[<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
<Rule '/pages/<page>' (HEAD, OPTIONS, GET) -> simple_page.show>,
<Rule '/pages/' (HEAD, OPTIONS, GET) -> simple_page.show>]
總之,你可以多次注冊(cè)藍(lán)圖,但是不一定每個(gè)藍(lán)圖都能正確響應(yīng)。是否能夠多次注冊(cè)實(shí)際 上取決于你的藍(lán)圖是如何編寫的,是否能根據(jù)不同的位置做出正確的響應(yīng)。
藍(lán)圖還可以用于提供資源。有時(shí)候,我們僅僅是為了使用一些資源而使用藍(lán)圖。
和普通應(yīng)用一樣,藍(lán)圖一般都放在一個(gè)文件夾中。雖然多個(gè)藍(lán)圖可以共存于同一個(gè)文件夾中,但是最好不要這樣做。
文件夾由 Blueprint 的第二個(gè)參數(shù)指定,通常為 __name__ 。這個(gè)參數(shù)指定與藍(lán)圖相關(guān)的邏輯 Python 模塊或包。如果這個(gè)參數(shù)指向的是實(shí)際的 Python 包(文件 系統(tǒng)中的一個(gè)文件夾),那么它就是資源文件夾。如果是一個(gè)模塊,那么這個(gè)模塊包含的 包就是資源文件夾??梢酝ㄟ^ Blueprint.root_path 屬性來查看藍(lán)圖的資源文件夾:
>>> simple_page.root_path
'/Users/username/TestProject/yourapplication'
可以使用 open_resource() 函數(shù)快速打開這個(gè)文件夾中的資源:
with simple_page.open_resource('static/style.css') as f:
code = f.read()
藍(lán)圖的第三個(gè)參數(shù)是 static_folder 。這個(gè)參數(shù)用以指定藍(lán)圖的靜態(tài)文件所在的文件夾,它可以是一個(gè)絕對(duì)路徑也可以是相對(duì)路徑。:
admin = Blueprint('admin', __name__, static_folder='static')
缺省情況下,路徑最右端的部分是在 URL 中暴露的部分。上例中的文件夾為 static ,那么 URL 應(yīng)該是藍(lán)圖加上 /static 。藍(lán)圖注冊(cè)為 /admin ,那么 靜態(tài)文件夾就是 /admin/static 。
端點(diǎn)的名稱是 blueprint_name.static ,因此你可以使用和應(yīng)用中的文件夾一樣的方法 來生成其 URL:
url_for('admin.static', filename='style.css')
如果你想使用藍(lán)圖來暴露模板,那么可以使用 Blueprint 的 template_folder 參數(shù):
admin = Blueprint('admin', __name__, template_folder='templates')
和靜態(tài)文件一樣,指向藍(lán)圖資源文件夾的路徑可以是絕對(duì)的也可以是相對(duì)的。藍(lán)圖中的 模板文件夾會(huì)被添加到模板搜索路徑中,但其優(yōu)先級(jí)低于實(shí)際應(yīng)用的模板文件夾。這樣在 實(shí)際應(yīng)用中可以方便地重載藍(lán)圖提供的模板。
假設(shè)你的藍(lán)圖便于 yourapplication/admin 中,要渲染的模板是 'admin/index.html' , template_folder 參數(shù)值為 templates ,那么真正的 模板文件為: yourapplication/admin/templates/admin/index.html 。
如果要?jiǎng)?chuàng)建頁面鏈接,可以和通常一樣使用 url_for() 函數(shù),只是要把藍(lán)圖名稱作為端點(diǎn)的前綴,并且用一個(gè)點(diǎn)( . )來 分隔:
url_for('admin.index')
另外,如果在一個(gè)藍(lán)圖的視圖函數(shù)或者被渲染的模板中需要鏈接同一個(gè)藍(lán)圖中的其他端點(diǎn),那么使用相對(duì)重定向,只使用一個(gè)點(diǎn)使用為前綴:
url_for('.index')
如果當(dāng)前請(qǐng)求被分配到 admin 藍(lán)圖端點(diǎn)時(shí),上例會(huì)鏈接到 admin.index 。
? Copyright 2013, Armin Ronacher. Created using Sphinx.