python實現(xiàn)web應(yīng)用框架之增加動態(tài)路由
今天我們將繼續(xù)對該框架進行路由添加正則表達式。
本篇文章所依賴的python環(huán)境為:

路由添加正則表達式有什么用?
在介紹之前,我們首先要介紹一下Get獲取資源的時候,有如下幾種傳參方式:
- 使用
key...value的形式,將參數(shù)放到url問號?后面,如:http://127.0.0.1/userInfo?name=pdudo - 在
url中以路徑參數(shù)的方式傳遞,例如:http://127.0.0.1/userInfo/pdudo/info。 - 在請求頭中傳遞參數(shù),請求頭是以
key...value的形式存儲的,當(dāng)然也可以自定義存放請求參數(shù)。
上述的第二種以路徑參數(shù)的方式傳參,就是我們這邊文章所描述的點。
為什么需要這樣做呢?
假設(shè)我們現(xiàn)在正在寫一個功能,他需要返回傳上來的用戶信息,接口為: /userInfo/userid/infos,其中userid是動態(tài)的,所以接口可以是/userInfo/c12345/infos,也可以是/userInfo/d33456/infos等等。
如果是這種情況,我們應(yīng)該怎么樣樣定義路由呢? 是在項目中給每個人都定義一個路由信息么?
很顯然不是的,如果這個時候,注冊的路由恰恰好是正則的,可以獲取客戶端傳上來的參數(shù),例如:/userInfo/pdudo/info,函數(shù)將會獲取pdudo,這樣不是很好么?
這就需要用到正則了。
如何定義動態(tài)路由
由于我們此前已經(jīng)寫好了定義靜態(tài)路由的相關(guān)方法,所以我們在定義動態(tài)路由的時候,最好加一個識別參數(shù),告訴框架,這個路由是靜態(tài)的 還是 動態(tài)的。
由于是動態(tài)路由,所以在路由url中,有些值肯定是動態(tài)的,如何在區(qū)別于靜態(tài)的值和動態(tài)的值呢? 在該框架中,我們將動態(tài)值用大括號括起來,比如: /userInfo/{userID}/infos,其中userID是動態(tài)的,可以是任何值組成,但是/userInfo和/infos必須是靜態(tài)的,而且先后順序也是固定的。
所以說,我們可以約束一下,在定義動態(tài)路由的時候,需要告訴框架,我這個是動態(tài)路由,以及動態(tài)url。
所以我們準(zhǔn)備將動態(tài)路由定義規(guī)劃如下:
@myWeb.routes(path="/jobs/{jobID}/startd",methods="post",regular=True)
def startJobs(r,cData):
print("cData: " ,cData)上述代碼,是我們即將完善功能后的代碼案例,其中regular為True代表該路由是動態(tài)的,path的值為/jobs/{jobID}/startd,其中jobID也是動態(tài)的,可以被任何值代替。
最后是函數(shù)將接收2個參數(shù),r的值代表wsgi中的environ信息。 而cData則代表從客戶端上報的值,即:jobID的替代值。
注冊動態(tài)路由
如上我們已經(jīng)約束好了一個動態(tài)路由的添加規(guī)則,那么我們?nèi)绾巫詣討B(tài)路由呢?
首先肯定的是,動態(tài)路由肯定不能和靜態(tài)路由放在一起,所以我們定義了新的字典用于存放動態(tài)路由的信息,如:
mapGetRegularRouting = {}
mapPostRegularRouting = {}而后則是我們需要將注冊的路由信息轉(zhuǎn)換為正則表達式,這里舉個例子:
我們注冊的路由是這樣的: /jobs/{jobID}/startd,我們需要將其轉(zhuǎn)換為正則表達式,正則表達式的值是這樣的: ^/jobs/(.*?)/startd$。
關(guān)于這段正則表達式,它的含義是 匹配以/jobs/開頭和/startd結(jié)尾的字符串,并且將匹配到的信息(.*的值)存儲到元組中。
注意這里.*后面的問號?代表不啟用貪婪匹配,也就是最小化匹配。
現(xiàn)在的問題是,如何將{jobsID}給轉(zhuǎn)換為(.*?)呢? 在python中,可以使用re.sub進行替換操作,我們可以使用如下語句,將{jobsID}給替換為(.*?),代碼如下:
import re
print(re.sub("{.*?}","(.*?)","/jobs/{jobID}/startd"))如上代碼執(zhí)行的結(jié)果為:

最后將該路由信息存儲到上述定義好的字典中即可,代碼片段如下:
reFindall = re.compile(r"{(.*?)}")
reSubAll = re.compile(r"{.*?}")
parameter = re.findall(reFindall,self.path)
reText = re.sub(reSubAll,"(.*?)",self.path)
reText = f"{reText}$"
regular = {
"original": self.path,
"reText": reText,
"parameter": parameter,
"func": func
}
# ...
if self.re:
mapPostRegularRouting[regular["reText"]] = regular至此,我們的動態(tài)路由就已經(jīng)注冊好了。
匹配動態(tài)路由
相比于注冊動態(tài)路由,當(dāng)客戶端請求來了之后,匹配動態(tài)路由會很麻煩,因為沒有請求報文不是告訴你,這是動態(tài)路由還是靜態(tài)路由,所以說,匹配動態(tài)路由很麻煩。
我們匹配動態(tài)路由想到的時候笨辦法,即: 先匹配靜態(tài)路由,若靜態(tài)路由匹配不到,則再匹配動態(tài)路由,若動態(tài)路由都匹配不到的話,則選用默認(rèn)路由。
匹配靜態(tài)路由和動態(tài)路由,前面篇章已經(jīng)介紹過了,所以這里不再贅述,這里就介紹如何匹配動態(tài)路由。
所謂的動態(tài)路由規(guī)則匹配,實際上就是拿著客戶端上傳的url,挨個對我們已有的正則表達式做輪訓(xùn),若匹配成功則退出循環(huán),若匹配失敗,最后就返回一個默認(rèn)路由即可,匹配正則表達式代碼如下:
for key in RegularRouting.keys():
if re.match(key, path):
isRegular = True
collText = re.findall(key, path)
func = RegularRouting[key]["func"]
break
else:
func = Route["/*"]框架運行效果展示
關(guān)于
myWeb.py由于很長,有100多行,不好截圖,也不好純復(fù)制代碼了,所以放到了gitee上面:gitee.com/pdudo/golea…
我們簡單寫幾個demo測試一下web框架,代碼如下:
import myWeb
import wsgiref.simple_server
@myWeb.routes(path="/ip",methods="all")
def indx(r):
print(r["REMOTE_ADDR"])
return (200,r["REMOTE_ADDR"])
@myWeb.routes(path="/hello/{name}",methods="get",regular=True)
def helloWold(r,cData):
name = cData[0]
return (200,"hello %s" % (name))
def main():
s = wsgiref.simple_server.make_server('', 8888, myWeb.application)
s.serve_forever()
if __name__ == '__main__':
main()上述代碼,我們首先引入了myWeb和wsgiref模塊,前置是我們自己寫的,后則是一個滿足wsgi服務(wù)器框架,在代碼中,我們定義了2個路由信息,一個是靜態(tài)路由,一個是動態(tài)路由,其中靜態(tài)路由的函數(shù)是indx,路由信息是/ip,匹配的客戶端請求方法為get或者post,該方法主要返回ip地址。
動態(tài)路由的函數(shù)則是helloWold,它將匹配到以/hello/為首的路由信息,匹配客戶端請求方法為get,還函數(shù)主要獲取用戶發(fā)送的動態(tài)值,并且以hello 等返回給客戶端。
在主函數(shù)中,我們啟動一個簡單的wsgi服務(wù)器,入口為myWeb的application方法 。
代碼運行效果如下:

我們分別使用get和post方法,請求本地/ip路由,可見都回復(fù)回來了,而后我們訪問/hello/pdudo和/hello/juejin,他們也分別回復(fù)了hello pdudo和hello juejin。
總結(jié)
本篇文件介紹了將此前的web框架,路由修改為正則表達式形式,具體添加方式為: 在進行路由注冊的時候,將其路由信息轉(zhuǎn)換為正則表達式,而在進行路由匹配的時候,先匹配靜態(tài)服務(wù)器,若靜態(tài)服務(wù)器沒有,再進行正則匹配,若正則匹配依然不行,則返回最后的默認(rèn)頁面。
以上就是python實現(xiàn)web應(yīng)用框架之增加動態(tài)路由的詳細(xì)內(nèi)容,更多關(guān)于python增加動態(tài)路由的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python-opencv 將連續(xù)圖片寫成視頻格式的方法
今天小編就為大家分享一篇python-opencv 將連續(xù)圖片寫成視頻格式的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-01-01
python字符串加密解密的三種方法分享(base64 win32com)
這篇文章主要介紹了python字符串加密解密的三種方法,包括用base64、使用win32com.client、自己寫的加密解密算法三種方法,大家參考使用吧2014-01-01
Python使用Selenium爬取淘寶異步加載的數(shù)據(jù)方法
今天小編就為大家分享一篇Python使用Selenium爬取淘寶異步加載的數(shù)據(jù)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-12-12
在Linux系統(tǒng)上安裝Python的Scrapy框架的教程
這篇文章主要介紹了在Linux系統(tǒng)上安裝Python的Scrapy框架的教程,Scrapy是著名的專門針對搜索引擎的爬蟲制作而研發(fā)的Python框架,需要的朋友可以參考下2015-06-06
關(guān)于Django顯示時間你應(yīng)該知道的一些問題
將Django項目部署到Linux系統(tǒng)上進行測試時,發(fā)現(xiàn)操作記錄的時間與服務(wù)器的時間不一致,相差13個小時。這主要是因為時區(qū)的問題,下面這篇文章主要總結(jié)介紹了關(guān)于Django顯示時間你應(yīng)該知道的一些問題,需要的朋友可以參考下。2017-12-12

