需求分析: 當一個龐大的系統中有很多小模塊,在分配路由的時候怎麼處理呢?全部都堆到一個py程式中,調用@app.route? 顯然這是很不明智的,因為當有幾十個模塊需要寫路由的時候,這樣程式員寫著寫著自己就暈掉了。同時也違背了面向對象設計原則中的控制反轉原則。模塊與模塊之間應該不要太緊密的依賴,高級 ...
需求分析:
當一個龐大的系統中有很多小模塊,在分配路由的時候怎麼處理呢?全部都堆到一個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 #上下文環境