Windows 10家庭中文版,Python 3.6.4,Flask 1.0.2,Eclipse Oxygen.1a Release (4.7.1a),PyDev 6.3.2html
本文爲記錄本身第一次使用Blueprints來搭建Flask項目,主要參考官方文檔Modular Applications with Blueprints(後面簡稱‘【官文】「)進行測試。flask
本文基於前面一篇博文介紹的bigflask項目進行測試——添加更多代碼、改造項目結構。api
關於Blueprints的一些Q&A:併發
有什麼用?極大地簡化大型Flask項目的開發。app
怎麼作到的?模塊化,大型項目一定由不一樣的應用模塊組成(劃分應用模塊是一個須要練習的工做),將不一樣的應用模塊劃分到不一樣的Blueprints中便可。模塊化
工做機制是怎樣的?首先使用Blueprint的裝飾器route將一些視圖函數匯合到到相應的Blueprint,而後再將Blueprint根據 URL 或 域名 等註冊(註冊函數register_blueprint)到Flask應用對象(本測試中只有一個應用對象,實際上能夠有多個,這須要經過應用建立工廠實現)中。完成上面的工做後,用戶就能夠經過不一樣的 URL 或 域名 訪問不一樣的Blueprint中的資源了。函數
怎麼創建Blueprint?和Flask應用同樣,能夠將一個Blueprint對象創建在單獨的Python模塊文件中,也能夠創建在一個package中。直接使用Blueprint構造器函數構造Blueprint對象便可。測試
關於Blueprints的其它介紹:url
當Blueprint是一個package時,它能夠擁有本身獨立的資源文件,如靜態文件、模板文件,在Blueprint構造器中定義,注意事項參考【官文】;spa
一個Blueprint能夠根據URL或域名的不一樣在同一個Flask上註冊屢次(url_prefix);
以前使用Flask應用的裝飾器route裝飾視圖函數,如今使用Blueprint對象的裝飾器route裝飾視圖函數,二者能夠同時使用,但要避免URL或域名衝突,當衝突發生時,在今天測試中會訪問使用Flask應用的裝飾器裝飾的視圖函數(原理待研究);
Blueprints測試記錄
測試能夠分爲三個部分:
Blueprint位於單個模塊文件中、Blueprint位於package中、存在多個Blueprints
Part 1.Blueprint位於單個模塊文件中
這個很簡單,直接把【官文】中的My First Blueprint中的代碼拷貝到一個Python模塊中,而後按照【官文】中Registering Blueprints中的方式進行註冊便可。
1 # bp1.py 2 3 from flask import Blueprint, render_template, abort 4 from jinja2 import TemplateNotFound 5 6 simple_page = Blueprint('simple_page', __name__, template_folder='templates') # 構造Blueprint對象,並指定了模型文件 7 8 print('simple_page.root_path: ', simple_page.root_path) 9 10 @simple_page.route('/', defaults={'page':'index'}) # 使用裝飾器route對函數show進行裝飾,兩個連接形式都指向show函數 11 @simple_page.route('/<page>') 12 def show(page): 13 print('Printed in show()') 14 try: 15 return render_template('pages/%s.html' % page) # 找到模板頁面,返回 16 except TemplateNotFound: 17 abort(404) # 沒找到模板頁面,返回404錯誤
註冊Blueprint到Flask應用很簡單,分兩步:導入Blueprint對象、使用Flask應用的register_blueprint函數註冊。
1 ... 2 from bigflask.bp1 import simple_page # Blueprint模塊前有Flask應用的名稱;只是導入Blueprint(在一個package可能存在多個Blueprints,此時,能夠導入多個,但【官文】不推薦這種作法); 3 ... 4 app.register_blueprint(simple_page) # 註冊到Flask應用;沒有制定URL或域名,默認綁定到'/'
項目目錄結構:另外添加了一個模板文件tmpt0.html——注意其路徑
運行應用,測試:
由於只有一個tmpt0.html模板文件,因此,使用其它地址進行測試時,都返回404錯誤。
重要說明:
在前面的bigflask項目中,使用Flask應用的裝飾器route裝飾了兩個URL:「/」和「/love」,所以,在個人測試中,訪問「/」和「/love」都顯示了正常頁面的內容。在將Flask應用的裝飾器相關程序取消後,這兩個頁面就返回404錯誤了。這也說明,Flask應用的裝飾器route的優先級比Blueprint裝飾器route要高。
進一步測試Blueprint註冊時的指定URL或域名
將在前面Blueprint註冊到Flask應用的函數總添加關鍵字參數url_prefix,以下:
1 app.register_blueprint(simple_page, url_prefix='/pages')
重啓Flask應用,測試:以前的連接找不到模板文件了,須要在其前面添加url_prefix(/pages)才能夠。
進一步測試——刪除註冊參數url_prefix的第一個斜槓,此時運行程序出錯:
1 app.register_blueprint(simple_page, url_prefix='pages')
啓動Flask發生錯誤:必須使用斜槓開頭,本身須要熟悉註冊函數的機制才能夠啊。
另外還檢查了app.root_path和Blueprint的root_path,在本部分單個模塊文件做爲Blueprint時,二者地址相同。
但在下一部分將Blueprint放到一個package中後,二者就不一樣了。
Part 2.Blueprint位於package中
在【官文】的Blueprint Resource Folder中說了,Blueprint能夠被放到package中,多個Blueprints也能夠放到一個package中,但後者不推薦。
Blueprint的資源目錄須要經過Blueprint構造器的第二個參數來推斷,默認是__name__,這個參數能夠指向一個Python模塊或一個包(本測試僅使用默認的__name__,指定一個Python模塊和一個包還須要更多測試),並能夠在程序中查看Blueprint.root_path來得知其路徑。【官文】中還介紹瞭如何快速打開一個Blueprint資源包下的文件,即便用open_resource()函數。
說明,進一步測試後,Flask應用也有root_path屬性和open_resouece()函數,功能和Blueprint相同。
看過【官文】後,知道Blueprint的package下還能夠包含獨立的靜態文件、模板文件,所以,在進行Part 2的測試時也添加了兩個文件夾並在其中添加了一些文件。
說明,前面測試建立Blueprint的模塊叫作bp1.py,這裏我創建了一個名爲bp1的package(PyDev不能夠在Package下創建Package,能夠先創建文件夾,再添加__init__.py文件),但沒有刪除bp1.py,在後來的測試中,發現bp1.py失效了,在導入時,from後面的bigflask.bp1指的是名爲bp1的package,而不是bp1.py模塊。
創建好的名爲bp1的package:將前面模塊bp1.py的代碼拷貝進去,並作一些修改
bp1 package下的__init__.py源碼截圖:創建Blueprint名爲simple_page_new
修改後的bigflask下的__init__.py源碼截圖:註冊bigflask下的bp1 package中的Blueprint simple_page_new
啓動Flask應用,測試:
注意,啓動過程當中發現一個url_for()函數的使用錯誤:緣由是因爲我在視圖函數外調用它了,錯誤提示是,在應用上下文可用時被執行
進一步測試:把上面的Blueprint註冊到多個URL——/bp1和/bpx
測試結果:成功。
Part 3.存在多個Blueprints
創建Blueprint所在包的方式和Part 2中相同,下面是創建了兩個Blueprint packages後的項目結構:
Blueprints註冊部分的源碼截圖:
測試結果:成功
至此,測試完畢。
後記
【官文】中有一些注意事項,在實際開發時須要注意,好比,Blueprint定義的模板文件夾的優先級比Flask應用的低等;
Blueprint構造器函數詳解;
register_blueprint註冊函數詳解;
Flask後臺怎麼處理的:這就須要更加深刻研究Flask,閱讀其源碼了——怎麼作到如此神奇的;
強化URL設計;
閱讀官方的示例程序,好比,Tutorial;
……
好了,如今能夠開發一個本身的【大型】Web應用併發布到Internet上吧!(注意,優勢浮躁了,才進不了一點點而已啊!穩住!)