解釋1:
允許將應(yīng)用組織為模塊留搔,每個(gè)模塊有自洽的 MVC惰匙,開發(fā)者做些工作可以使模塊間依賴盡可能少译红,必要時(shí)可以按 blueprint 為單位做垂直拆分预茄。
依賴反轉(zhuǎn),允許把 route 掛到 blueprint 對(duì)象而非全局 app 對(duì)象上侦厚。
解釋2:
1 概述
藍(lán)圖/Blueprint是Flask應(yīng)用程序組件化的方法耻陕,可以在一個(gè)應(yīng)用內(nèi)或跨越 多個(gè)項(xiàng)目共用藍(lán)圖。使用藍(lán)圖可以極大地簡(jiǎn)化大型應(yīng)用的開發(fā)難度刨沦,也為Flask擴(kuò)展 提供了一種在應(yīng)用中注冊(cè)服務(wù)的集中式機(jī)制诗宣。
2 初識(shí)藍(lán)圖
藍(lán)圖/Blueprint對(duì)象用起來和一個(gè)應(yīng)用/Flask對(duì)象差不多,最大的區(qū)別在于一個(gè) 藍(lán)圖對(duì)象沒有辦法獨(dú)立運(yùn)行想诅,必須將它注冊(cè)到一個(gè)應(yīng)用對(duì)象上才能生效召庞。
使用藍(lán)圖可以分為三個(gè)步驟
1.創(chuàng)建一個(gè)藍(lán)圖對(duì)象
ezbp =Blueprint("ezbp",__name__)
2.在這個(gè)藍(lán)圖對(duì)象上進(jìn)行操作,入注冊(cè)路由侧蘸、指定靜態(tài)文件夾裁眯、注冊(cè)模板過濾器...
@ezbp.route('/')defezbp_index():return'Welcome to my blueprint'
3.在應(yīng)用對(duì)象上注冊(cè)這個(gè)藍(lán)圖對(duì)象
app.register_blueprint(ezbp,url_prefix='/ezbp')
當(dāng)這個(gè)應(yīng)用啟動(dòng)后,通過/ezbp/可以訪問到藍(lán)圖中定義的視圖函數(shù)讳癌。
考察上面的代碼,可以看到在藍(lán)圖對(duì)象上注冊(cè)路由的方法和在應(yīng)用對(duì)象上完全 一樣存皂,那么晌坤,值得思考的是逢艘,藍(lán)圖和應(yīng)用對(duì)象的運(yùn)行機(jī)制是一樣的嗎?
example:
#-*- coding:utf-8 -*-fromflaskimportFlask,Blueprintapp= Flask(__name__)
@app.route('/')defapp_index():return'go blueprint'ezbp = Blueprint("ezbp",__name__)
@ezbp.route('/')defezbp_index():return'Welcome to my blueprint'app.register_blueprint(ezbp,url_prefix='/ezbp')
app.run(host='0.0.0.0',port=80)
ouptut:
3?運(yùn)行機(jī)制———說白了就是會(huì)自動(dòng)補(bǔ)充URL前綴骤菠,并且能使用相同的視圖函數(shù)
藍(lán)圖并不是一個(gè)可插拔的應(yīng)用 —— 它只是保存了一組將來可以在應(yīng)用對(duì)象上執(zhí)行 的操作—— 注冊(cè)路由就是一種操作它改。
當(dāng)在應(yīng)用對(duì)象上調(diào)用route 裝飾器或使用add_url_rule()方法注冊(cè)路由時(shí), 我們已經(jīng)知道商乎,這個(gè)操作將修改應(yīng)用對(duì)象的兩張路由表:url_map和view_functions央拖; 然而,藍(lán)圖對(duì)象根本就沒有路由表鹉戚,當(dāng)我們?cè)谒{(lán)圖對(duì)象上調(diào)用route裝飾器或使用?add_url_rule()方法注冊(cè)路由時(shí)鲜戒,它只是在內(nèi)部的一個(gè)延遲操作記錄列表defered_functions中添加了一項(xiàng):下圖為blueprint和FLask route的對(duì)比
lambad s: s.add_url_rule('/',view_func=ezbp_index)定義了一個(gè)匿名函數(shù), 參數(shù)s就是將來被傳入的應(yīng)用對(duì)象抹凳。當(dāng)執(zhí)行應(yīng)用對(duì)象的register_blueprint()方法時(shí)遏餐,應(yīng)用對(duì)象將從藍(lán)圖對(duì)象的defered_functions列表中取出每一項(xiàng),并以自身 作為參數(shù)執(zhí)行該匿名函數(shù) —— 即調(diào)用應(yīng)用對(duì)象的add_url_rule()方法赢底,這將真正的 修改應(yīng)用對(duì)象的兩張路由表失都。
所以說,藍(lán)圖這個(gè)名字起得的確恰當(dāng)幸冻,藍(lán)圖的那些方法僅僅記錄了未來應(yīng)該發(fā)生的操作粹庞, 而不是當(dāng)即實(shí)現(xiàn)。
2 藍(lán)圖的URL前綴
繼續(xù)使用前一節(jié)的圖洽损,注意其中被橘黃色熒光筆涂抹的代碼:
當(dāng)我們?cè)趹?yīng)用對(duì)象上注冊(cè)一個(gè)藍(lán)圖時(shí)庞溜,需要指定一個(gè)url_prefix關(guān)鍵字 參數(shù)(這個(gè)參數(shù)默認(rèn)是/)。在上面的圖中可以看到趁啸,在應(yīng)用最終的路由表url_map中强缘,在藍(lán)圖上注冊(cè)的路由URL自動(dòng)被加上了這個(gè)前綴。
這相當(dāng)有用不傅,我們可以在多個(gè)藍(lán)圖中使用相同的URL規(guī)則而不會(huì)最終引起沖突旅掂,只要在 注冊(cè)藍(lán)圖時(shí)將不同的藍(lán)圖掛接到不同的自路徑即可 —— 想一想對(duì)于大型應(yīng)用而言,不同 的藍(lán)圖通常是不同的人員開發(fā)的访娶,你很難保證URL規(guī)則不發(fā)生沖突商虐!
example:
#-*- coding:utf-8 -*-fromflaskimportFlask,Blueprint
shop= Blueprint('shop','shop')
@shop.route('/')defv_index():return'shop root'vip= Blueprint('vip','vip')
@vip.route('/')defv_index():return'vip homepage'admin= Blueprint('admin','admin')
@admin.route('/')defv_index():return'admin root'app= Flask(__name__)
app.register_blueprint(shop,url_prefix='/')
app.register_blueprint(admin,url_prefix='/admin')
app.register_blueprint(vip,url_prefix='/vip')
app.run(host='0.0.0.0',port=80)
output:
4?藍(lán)圖的endpoint———加上藍(lán)圖前綴
圖繼續(xù),這次關(guān)注綠色熒光筆涂抹的代碼:
我們創(chuàng)建藍(lán)圖對(duì)象時(shí)崖疤,第一個(gè)參數(shù)指定了藍(lán)圖的名字秘车。當(dāng)在應(yīng)用中注冊(cè)藍(lán)圖時(shí), 藍(lán)圖的路由項(xiàng)中的訪問點(diǎn)endpoint被自動(dòng)添加了這個(gè)名字劫哼。
這有什么用叮趴?這涉及到url_for()的正確工作與否。
當(dāng)不同的團(tuán)隊(duì)開發(fā)不同的藍(lán)圖時(shí)权烧,和URL規(guī)則類似眯亦,你很難保證他們的視圖函數(shù)名 彼此不同伤溉,尤其像index這樣俗套的名字。如果不對(duì)來自不同藍(lán)圖的endpoint 進(jìn)行區(qū)隔妻率,那么url_for('index')到底應(yīng)該生成那個(gè)URL乱顾?這顯然無法確定。
一旦給不同藍(lán)圖的endpoint加上了藍(lán)圖名前綴宫静,我們可以確切地告訴url_for()?了:
url_for('shop.v_index')#/shop/url_for('admin.v_index')#/admin/
example:
#-*- coding:utf-8 -*-fromflaskimportFlask,Blueprint,url_for,render_template_string
shop= Blueprint('shop',__name__)
@shop.route('/')defv_index():return'''
@admin.route('/')defv_index():return'''
app.register_blueprint(shop,url_prefix='/shop')
app.register_blueprint(admin,url_prefix='/admin')
@app.route('/')defv_index():
tpl='''
'''returnrender_template_string(tpl)
app.run(host='0.0.0.0',port=80)
ouput:
5?注冊(cè)靜態(tài)目錄路由
和應(yīng)用對(duì)象不同走净,藍(lán)圖對(duì)象創(chuàng)建時(shí)不會(huì)默認(rèn)注冊(cè)靜態(tài)目錄的路由。需要我們?cè)?創(chuàng)建時(shí)指定static_folder參數(shù)孤里。
下面的示例將藍(lán)圖所在目錄下的ezstatic目錄設(shè)置為靜態(tài)目錄:
admin = Blueprint("admin",__name__,static_folder='ezstatic')
app.register_blueprint(admin,url_prefix='/admin')
默認(rèn)情況下Flask使用文件夾的名稱注冊(cè)靜態(tài)文件夾的路由:
+------------------------------------------------------------------+
|? url? ? ? ? ? ? | endpoint? ? ? ? | view_function? ? ? ? ? ? ? |
+------------------------------------------------------------------+
|? /admin/ezstatic | admin.static? ? | Blueprint.send_static_file |
+------------------------------------------------------------------+
現(xiàn)在就可以使用/admin/ezstatic/訪問mystatic目錄下的靜態(tài)文件了伏伯。
定制靜態(tài)目錄URL規(guī)則?:可以在創(chuàng)建藍(lán)圖對(duì)象時(shí)使用static_url_path來改變靜態(tài) 目錄的路由。下面的示例將為ezstatic文件夾的路由設(shè)置為/lib:
admin = Blueprint("admin",__name__,static_folder='ezstatic',static_url_path='/lib')
app.register_blueprint(admin,url_prefix='/admin')
這時(shí)的路由表如下:
+------------------------------------------------------------------+
|? url? ? ? ? ? ? | endpoint? ? ? ? | view_function? ? ? ? ? ? ? |
+------------------------------------------------------------------+
|? /admin/lib? ? ? | admin.static? ? | Blueprint.send_static_file |
+------------------------------------------------------------------+
這樣我們可以使用地址/admin/lib/main.css訪問ezstatic目錄下的main.css文件了