Werkzeug庫:routing模塊
來源: Learn Python
fanchunke.me/Flask/Werkzeug庫——routing模塊/
Werkzeug庫的routing模塊的主要功能在於URL解析。對於WSGI應用來講,不同的URL對應不同的視圖函數,routing模塊則會對請求信息的URL進行解析並匹配,觸發URL對應的視圖函數,以此生成一個響應信息。routing模塊的解析和匹配功能主要體現在三個類上:Rule、Map和MapAdapter。
Rule類
Rule類繼承自RuleFactory類。一個Rule的實例代表一個URL模式,一個WSGI應用可以處理很多不同的URL模式,這也就是說可以產生很多不同的Rule實例。這些Rule實例最終會作為參數傳遞給Map類,形成一個包含所有URL模式的對象,通過這個對象可以解析並匹配請求對應的視圖函數。
關於Rule類有一些常用的方法:
empty() ——在實際情況中,Rule實例會和一個Map實例進行綁定。通過empty()方法可以將Rule實例和Map實例解除綁定。
get_empty_kwargs() ——在empty()方法中調用,可以獲得之前Rule實例的參數,以便重新構造一個Rule實例。
get_rules(map) ——這個方法是對RuleFactory類中get_rules方法的重寫,返回Rule實例本身。
refresh() ——當修改Rule實例(URL規則)後可以調用該方法,以便更新Rule實例和Map實例的綁定關係。
bind(map, rebind=False) ——將Rule實例和一個Map實例進行綁定,這個方法會調用complie()方法,會給Rule實例生成一個正則表達式。
complie() ——根據Rule實例的URL模式,生成一個正則表達式,以便後續對請求的path進行匹配。
match(path) ——將Rule實例和給定的path進行匹配。在調用complie()方法生成的正則表達式將會對path進行匹配。如果匹配,將返回這個path中的參數,以便後續過程使用。如果不匹配,將會由其他的Rule實例和這個path進行匹配。
注意: 在對給定的URL進行匹配的過程中,會使用一些Converters。關於Converters的信息後續加以介紹。
Map類
通過Map類構造的實例可以存儲所有的URL規則,這些規則是Rule類的實例。Map實例可以 通過後續的調用和給定的URL進行匹配。
關於Map類有一些常用的方法:
add(rulefactory) ——這個方法在構造Map實例的時候就會調用,它會將所有傳入Map類中的Rule實例和該Map實例建立綁定關係。該方法還會調用Rule實例的bind方法。
bind方法 ——這個方法會生成一個MapAdapter實例,傳入MapAdapter的包括一些請求信息,這樣可以調用MapAdapter實例的方法匹配給定URL。
bind_to_environ方法 ——通過解析請求中的environ信息,然後調用上面的bind方法,最終會生成一個MapAdapter實例。
MapAdapter類
MapAdapter類執行URL匹配的具體工作。關於MapAdapter類有一些常用的方法:
dispatch方法 ——該方法首先會調用MapAdapter實例的match()方法,如果有匹配的Rule,則會執行該Rule對應的視圖函數。
match方法 ——該方法將會進行具體的URL匹配工作。它會將請求中的url和MapAdapter實例中的所有Rule進行匹配,如果有匹配成功的,則返回該Rule對應的endpoint和一些參數rv。endpoint一般會對應一個視圖函數,返回的rv可以作為參數傳入視圖函數中。
一個簡單的例子
為了說明routing模塊的工作原理,這裡使用Werkzeug文檔中的一個例子,稍加改動後如下所示:
fromwerkzeug.routingimportMap,Rule,NotFound,RequestRedirect,HTTPException
url_map=Map([
Rule( / ,endpoint= blog/index ),
Rule( // ,endpoint= blog/archive ),
Rule( /// ,endpoint= blog/archive ),
Rule( //// ,endpoint= blog/archive ),
Rule( //// ,
endpoint= blog/show_post ),
Rule( /about ,endpoint= blog/about_me ),
Rule( /feeds/ ,endpoint= blog/feeds ),
Rule( /feeds/.rss ,endpoint= blog/show_feed )
])
defapplication(environ,start_response):
urls=url_map.bind_to_environ(environ)
try:
endpoint,args=urls.match()
exceptHTTPException,e:
returne(environ,start_response)
start_response( 200 OK ,[( Content-Type , text/plain )])
return[ Rule points to %r with arguments %r %(endpoint,args)]
if__name__== __main__ :
fromwerkzeug.servingimportrun_simple
run_simple( localhost ,4000,application)
這裡我們使用werkzeug自帶的伺服器模塊構造了一個Web伺服器,並且設計了一個簡單的WSGI應用——application。這個Web伺服器可以根據URL的不同返回不同的結果。關於伺服器的構造這裡不再贅述,以下部分簡單對URL Routing過程進行分析:
1. 設計URL模式
設計URL模式的過程就是構造Rule實例的過程。上面的例子中我們構造了8個Rule實例,分別對應8個不同的URL模式。每個Rule實例還對應一個endpoint,這個endpoint可以和視圖函數進行對應,以便訪問某個URL時,可以觸發與之對應的視圖函數。下面的例子展示了endpoint和視圖函數的對應關係。
fromwerkzeug.wrappersimportResponse
fromwerkzeug.routingimportMap,Rule
defon_index(request):
returnResponse( Hello from the index )
url_map=Map([Rule( / ,endpoint= index )])
views={ index :on_index}
2. 構造Map實例
構造Map實例時,會調用它的add(rulefactory)方法。這個方法會在Map實例和各個Rule實例之間建立綁定關係,並通過調用Rule實例的bind()方法為每個Rule實例生成一個正則表達式。
例如,對於 /about 這個URL,它對應的正則表達式為:
^\\/about$
對於 //// 這個URL,它對應的正則表達式為:
^\\/(?P\d+)\/(?P\d+)\/(?P\d+)(?/?)$
3. 構造MapAdapter實例
在設計WSGI應用時,上述例子通過url_map.bind_to_environ(environ)構建了一個MapAdapter實例。這個實例將請求的相關信息和已經創建好的Map實例放在一起,以便進行URL匹配。
進行URL匹配的過程是通過調用MapAdapter實例的match()方法進行的。實質上,這個方法會將請求中的path傳入到所有Rule實例的match(path)方法中,經過正則表達式的匹配來分析path是否和某個Rule實例匹配。如果匹配則返回對應的endpoint和其他的參數,這可以作為參數傳入視圖函數。
4. 訪問URL可得相關結果
之後,訪問URL可以得到相對應的結果。
例如,訪問http://localhost:4000/2017/,可以得到:
Rule points to blog/archive with arguments { year : 2017}
訪問http://localhost:4000/2017/3/20/,可以得到:
Rule points to blog/archive with arguments { month : 3, day : 20, year : 2017}
訪問http://localhost:4000/about,可以得到:
Rule points to blog/about_me with arguments {}
看完本文有收穫?請轉發分享給更多人
關注「Python開發者」,提升Python技能
※Python 增強的生成器:協程
※Python這麼熱,要不要追趕 Python 的熱潮?
※Python :淺析 return 和 finally 共同挖的坑
※頂會審稿人領你打開深度學習的大門
※Python 線性分類模型簡介
TAG:Python開發者 |