Flask路由與藍圖Blueprint
需求分析:
當一個龐大的系統中有很多小模組,在分配路由的時候怎麼處理呢?全部都堆到一個py程式中,呼叫@app.route? 顯然這是很不明智的,因為當有幾十個模組需要寫路由的時候,這樣程式設計師寫著寫著自己就暈掉了。同時也違背了面向物件設計原則中的控制反轉原則。模組與模組之間應該不要太緊密的依賴,高階層級模組和低階層級的模組之間的依賴應該有一層抽象來實現。
Flask框架中,我們可以使用blueprint藍圖來解耦路由分配問題,實現不同業務模組之間的較為鬆散的依賴。
1. blueprint的實現過程
(1)在子模組views.py檔案中定義藍圖
例如:為customer定義一個藍圖路由
customer = Blueprint('customer',__name__) @customer.route() def do_something(): pass
(2)在主模組views.py檔案中註冊藍圖
app.register_blueprint(customer,url_prefix='/customer')
Blueprint()函式解析,Blueprint實際上是一個類
官方文件的定義: def __init__(self, name, import_name, static_folder=None, static_url_path=None, template_folder=None, url_prefix=None, subdomain=None, url_defaults=None, root_path=None):
有兩個是必須填寫的引數:name和import name,其餘引數都是選擇性的
1. name:即路由的別名,在子模組中定義的藍圖要想通過在主模組中註冊使用,就需要定義一個別名
2. import name:表示模組的系統變數,用來區別是子模組還是主模組,這裡必須填__name__,表示是在子模組中定義
3. url_prefix:路由字首
例如:想到達http://myblog/article/first
/artile 即是 first字首
4. template_folder:模板資料夾
如果想從其他模組的模板資料夾中排程模板來使用,需要使用template_folder來指明模板的搜尋路徑
同樣的,static_folder與static_url_path的功能與template_folder類似
5. url_defaults :預設的路由路徑別名,以字典的形式儲存在Blueprint類例項中。
因為儲存的形式是字典,所以這個引數的值比較特殊,一定是要含有兩個引數的元組形式。
例如:url_defaults=([‘so’,’so’])
有一種引數形式的路由設定方式:
@customer.route(‘/<int : any>’)
def do_something(any):
pass
路由引數在客戶端輸入的值時不確定的,如上面規定的int即整型數(也可以是string型別或者不設定型別)。在定義路由函式的時候,必須作為形參傳入。那麼如果設定了url_defaluts,則這個形參的名稱就固定了,不可以為其他。例如上面的例子:url_defaults=([‘so’,’so’]),那麼,形參就必須為so,而不能是any了。顯然,blueprint的這個引數能夠有效定義路由的具體功能,使一個路由更具體化,避免程式編寫過程中隨意的改動造成錯誤。
也就是說,一旦設定了這個引數值,那麼這個路由的別名就定死了。
6. root_path:根目錄的絕對路徑,一般為工程專案的根目錄路徑
2. 關於route方法
例子:
@app.route(‘ /’ ,’index’ , index)
def index():
pass
#帶引號的是endpoint,不帶引號的index是路由函式名,必須要與下面定義的函式名相同
route()其實是add_url_rule()方法的例項
@app.route(‘ /’ ,’index’,index)
等價於:app.add_url_rule(‘/’,’index’, index)
也可以這樣定義endpoint:
app.view_functions[‘index’] = index
官方原始碼:
add_url_rule(rule,endpoint=None,view_func=None,provide_automatic_options=None, **options)
引數解析:
1. rule:在瀏覽器輸入的地址格式
2. view_func:路由函式,即開發者定義的路由
If a view_func is provided it will be registered with the endpoint.
3. endpoint:路由函式的註冊別名
關於endpoint
endpoint相當於實際url的一個別名,在瀏覽器輸入地址時,需要在flask後臺尋找相應的路由函式(從而查詢相應的資源),而在查詢的過程中,不是直接用實體地址來進行硬編碼的,而是通過對映成endpoint來查詢。也就是說,開發者定義的每一個路由地址都有一個註冊的endpoint與之對應。在客戶端輸入地址在後臺查詢資源的時候,通過這個endpoint來查詢相應的路由函式。
深入理解Flask請求機制:
所有 Flask 程式都必須建立一個程式例項。 Web 伺服器把接收來自客戶端的所有請求路由都轉交給這個例項物件處理。程式例項是 Flask 類的物件。 Flask 類的建構函式只有一個必須指定的引數,即程式主模組或包的名字,即我們經常用到的一條語句:app = Flask(__name__)。Python的 __name__ 變數會儲存這些值。
另外,Flask 用藍圖 blueprint來在一個應用中或跨應用製作應用元件和支援通用的模式。通過不同的 url_prefix ,從而使使用者的請求到達不同模組的 view 函式。同時,有效分離了不同模組,使得開發過程更加的清晰。
app和藍圖blueprint還有許多類方法,像route()方法一樣可以作為路由函式的裝飾器,對每一次請求作更精細的判別和操作,在更高效地進行資料庫配置和請求操作,以及處理錯誤請求方面有很大的作用。下篇文章我將會寫一下這方面的內容。
參考閱讀:官方文件http://flask.pocoo.org/docs/dev/api/#flask.Flask.add_url_rule
例如:
before_first_request #第一次請求的處理
before_reqeust #註冊一個函式來實現對每一個路由請求的攔截
after_request #每一次請求之後額處理
app_context #上下文環境