python-django中的APPEND_SLASH實(shí)現(xiàn)方法
關(guān)于django中的APPEND_SLASH
APPEND_SLASH
它是啥?
看變量名大概能知道做什么,就是添加斜線(xiàn),用路由系統(tǒng)那里。
路由文件,只寫(xiě)了路由關(guān)系代碼
...... urlpatterns = [ url(r'^test/$', views.test), ] ......
APPEND_SLASH這個(gè)常量默認(rèn)為T(mén)rue,就是假如你沒(méi)有添加斜線(xiàn),他會(huì)幫你添加上(總體是這樣,具體得看源碼怎么寫(xiě)的了)
執(zhí)行命名行代碼啟動(dòng)django項(xiàng)目
python manage.py runserver
目前APPEND_SLASH=True,我們打開(kāi)瀏覽器的開(kāi)發(fā)者工具,查看網(wǎng)絡(luò)請(qǐng)求,輸入127.0.0.1:8000/test
這里我是沒(méi)有加斜線(xiàn)的
仔細(xì)看下網(wǎng)絡(luò)請(qǐng)求,我們輸入127.0.0.1:8000/test,看起來(lái)只發(fā)送了一次,其實(shí)真實(shí)發(fā)送了兩次請(qǐng)求。
我們繼續(xù)再訪(fǎng)問(wèn)這個(gè)url:127.0.0.1:8000/test11
,看看請(qǐng)求
我們也同樣訪(fǎng)問(wèn)了一個(gè)url,但是這次和上面不同的是,只發(fā)送了一次請(qǐng)求。
兩次都是發(fā)送一個(gè)get請(qǐng)求,訪(fǎng)問(wèn)服務(wù)器的一個(gè)資源。
第一次請(qǐng)求的url為127.0.0.1:8000/test
,我們的路由關(guān)系中是沒(méi)有這個(gè)url的,對(duì)沒(méi)錯(cuò),如果訪(fǎng)問(wèn)想要訪(fǎng)問(wèn)到服務(wù)器的資源必須為這樣的url才行127.0.0.1:8000/test/
,雖說(shuō)這兩個(gè)url看起來(lái)差不多,但其實(shí)差很多的。但是第一次請(qǐng)求的url只需在最后加上/
,就能訪(fǎng)問(wèn)到資源了,這就是APPEND_SLASH的作用。
第二次請(qǐng)求的url為127.0.0.1:8000/test11
,這個(gè)地址也不在我們的路由關(guān)系中,況且加上了/
,也不能訪(fǎng)問(wèn)到資源。所以總共發(fā)送了一次,最終返回了404錯(cuò)誤。
先大致總結(jié)下:APPEND_SLASH=True的情況下,先會(huì)根據(jù)前端傳來(lái)的url,先檢測(cè)這個(gè)url能不能訪(fǎng)問(wèn)資源,如果可以訪(fǎng)問(wèn)的話(huà),那么就去執(zhí)行相應(yīng)的業(yè)務(wù)代碼,最后返回。如果這個(gè)url不能訪(fǎng)問(wèn)到資源的話(huà),會(huì)判斷這個(gè)url最后有沒(méi)有/
,有/
的話(huà),則返回404錯(cuò)誤;如果沒(méi)有/
的話(huà),便會(huì)幫你加上/
,生成一個(gè)新的url,再去檢測(cè)這個(gè)新的url能不能訪(fǎng)問(wèn)到資源,如果能訪(fǎng)問(wèn)的話(huà),則返回301的狀態(tài)碼,并將這個(gè)新的url傳到前端,進(jìn)行重定向操作(這就是我們第一次請(qǐng)求出現(xiàn)的情況),如果這個(gè)新的url(幫你加上/
的)還是不能訪(fǎng)問(wèn)到資源的話(huà),也會(huì)返回404錯(cuò)誤(這就是我們第二次請(qǐng)求出現(xiàn)的情況)。這就是對(duì)上面出現(xiàn)情況的總結(jié)吧(具體流程還得去看源碼)
那么APPEND_SLASH=False的情況,就不會(huì)幫你加/
,你前臺(tái)傳怎樣的url,那就用這個(gè)url去訪(fǎng)問(wèn)資源,能不能訪(fǎng)問(wèn)還得看你url對(duì)不對(duì)。
在走到路由層之前,請(qǐng)求會(huì)先走到中間件這一層,在這一層就執(zhí)行了上面分析的邏輯
這一個(gè)中間件實(shí)現(xiàn)了上面的邏輯 'django.middleware.common.CommonMiddleware'
,請(qǐng)求來(lái)的時(shí)候,會(huì)走這個(gè)中間件的process_request
方法,下面來(lái)看這個(gè)方法寫(xiě)了什么
看這一句注釋?zhuān)? Check if a slash should be appended,檢測(cè)是否需要加上斜線(xiàn)
看這個(gè)方法should_redirect_with_slash
,返回值為bool類(lèi)型。返回True的情況是,APPEND_SLASH=True,這個(gè)url不是以/
結(jié)尾的,并且這個(gè)url添加上了/
,能夠訪(fǎng)問(wèn)資源的。必須滿(mǎn)足這三種情況,返回值為T(mén)rue,其他情況的話(huà)返回就是False。
下面貼上should_redirect_with_slash
的源碼
def should_redirect_with_slash(self, request): """ Return True if settings.APPEND_SLASH is True and appending a slash to the request path turns an invalid path into a valid one. """ if settings.APPEND_SLASH and not request.path_info.endswith('/'): urlconf = getattr(request, 'urlconf', None) return ( not is_valid_path(request.path_info, urlconf) and is_valid_path('%s/' % request.path_info, urlconf) ) return False
就說(shuō)下 is_valid_path
方法有啥作用吧。你可以去看源碼具體了解
is_valid_path
檢測(cè)傳進(jìn)去的url,是否能訪(fǎng)問(wèn)到資源。(說(shuō)白了就是判斷這個(gè)url是否存在我們定義的url映射中)
這樣的話(huà),上面這段代碼就很簡(jiǎn)單了。首先判斷APPEND_SLASH,如果為False的。那么這個(gè)方法should_redirect_with_slash
直接返回False。如果APPEND_SLASH為T(mén)rue的話(huà),再對(duì)請(qǐng)求的url進(jìn)行判斷,request.path_info
它的值并不是一個(gè)完整的url,而是ip+端口后面的那一部分(也就是例子中的/test
),判斷它是否以斜線(xiàn)(/
)結(jié)尾的,如果是的話(huà),那么not request.path_info.endswith('/')
整體就為False,所以if判斷后面的表達(dá)式就為False,最終返回了False。如果不是以斜線(xiàn)(/
)結(jié)尾的話(huà),那么if后面的表達(dá)式就為T(mén)rue,那么繼續(xù)執(zhí)行條件為真的代碼塊,這個(gè)代碼塊最終返回了一個(gè)表達(dá)式的結(jié)果,這個(gè)表達(dá)式類(lèi)型是這樣 bool and bool。也就是根據(jù)方法is_valid_path
d的返回值進(jìn)行判斷的,如果request.path_info
(代碼能分析到這里說(shuō)明它不是以斜線(xiàn)結(jié)尾的),首先判斷這個(gè)值能不能在我們寫(xiě)的路由關(guān)系映射中存不存在。存在的話(huà),方法is_valid_path
返回真,那么not True
就為False,and左邊的表達(dá)式為False,整體的表達(dá)式就為False,所以最終返回的就是False。如果request.path_info
的值在路由關(guān)系映射中不存在,那么and左邊的表達(dá)式為T(mén)rue,那就繼續(xù)看and右邊表達(dá)式的布爾值。and右邊還是調(diào)用了方法is_valid_path
,只不過(guò)傳的參數(shù)是request.path_info
+ /
,如果在路由映射中存在,那么最終返回True,如果不存在,那么就返回了False了。
should_redirect_with_slash
方法分析完畢,繼續(xù)看源碼
# Check if a slash should be appended if self.should_redirect_with_slash(request): path = self.get_full_path_with_slash(request) else: path = request.get_full_path()
后面根據(jù)should_redirect_with_slash
方法的返回值,做了不同的操作。不嚴(yán)格來(lái)說(shuō),不管True還是False,最終執(zhí)行了requests.get_full_path
這個(gè)方法,只不過(guò)傳入的參數(shù)不同的,最終返回了一個(gè)完整的url請(qǐng)求地址。
繼續(xù)往下看
# Return a redirect if necessary if redirect_url or path != request.get_full_path(): redirect_url += path return self.response_redirect_class(redirect_url)
如果if后面的表達(dá)式為T(mén)rue的話(huà),最終稿返回了一個(gè)狀態(tài)碼為301的Httpresponse對(duì)象,這個(gè)對(duì)象里帶這一個(gè)數(shù)據(jù),這個(gè)數(shù)據(jù)就是在原url基礎(chǔ)上加上斜線(xiàn)(/
)的新url,前端接收到狀態(tài)碼為301的響應(yīng),則會(huì)繼續(xù)請(qǐng)求響應(yīng)中攜帶的新地址。為False的話(huà),返回默認(rèn)返回None。
django的中間件會(huì)根據(jù)每個(gè)中間件里的process_request方法或者process_response方法不同的返回值會(huì)執(zhí)行相應(yīng)的操作,具體操作不說(shuō)了,不是這個(gè)知識(shí)點(diǎn)的內(nèi)容。
那么中間件的process_request
返回None的話(huà),則會(huì)執(zhí)行下一個(gè)中間件的process_request
的方法。如果返回的是HttpResponse對(duì)象的話(huà),則不會(huì)繼續(xù)執(zhí)行下一個(gè)中間件的process_request
方法,則會(huì)執(zhí)行process_response
方法。具體從哪個(gè)中間件執(zhí)行和django的版本有關(guān)系,反正是不會(huì)執(zhí)行路由對(duì)應(yīng)的視圖代碼的代碼,會(huì)直接返回給前端HttpResoonse對(duì)象。
好了,關(guān)于A(yíng)PPEND_SLASH的知識(shí)總結(jié)完畢。APPEND_SLASH它默認(rèn)為T(mén)rue,如果想要修改的話(huà),需要在settings.py文件中定義這個(gè)常量,賦值為False,這樣就可以覆蓋原django中配置文件里對(duì)應(yīng)的常量了。至于django內(nèi)部怎么操作的,下次再總結(jié)吧
最后還是補(bǔ)個(gè)圖吧,我把APPEND_SLASH設(shè)置為False,訪(fǎng)問(wèn)127.0.0.1:8000/test
如果你設(shè)置了APPEND_SLASH為False,訪(fǎng)問(wèn)上面這個(gè)url,還是能訪(fǎng)問(wèn)到頁(yè)面的話(huà),清理下瀏覽器的緩存,就可以了
總結(jié)
以上所述是小編給大家介紹的python-django中的APPEND_SLASH實(shí)現(xiàn),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
python Tornado事件循環(huán)示例源碼解析
這篇文章主要為大家介紹了python Tornado事件循環(huán)示例源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09使用pandas中的DataFrame數(shù)據(jù)繪制柱狀圖的方法
下面小編就為大家分享一篇使用pandas中的DataFrame數(shù)據(jù)繪制柱狀圖的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-04-04Python pass語(yǔ)句作用和Python assert斷言函數(shù)的用法
這篇文章主要介紹了Python pass語(yǔ)句作用和Python assert斷言函數(shù)的用法,文章內(nèi)容介紹詳細(xì)具有一定的參考價(jià)值,需要的小伙伴可以參考一下,希望對(duì)你有所幫助2022-03-03可用于監(jiān)控 mysql Master Slave 狀態(tài)的python代碼
用于監(jiān)控MySQL Master Slave 狀態(tài)的python代碼,有需要的朋友可以參考下2013-02-02Python多線(xiàn)程 Queue 模塊常見(jiàn)用法
Python的Queue模塊提供一種適用于多線(xiàn)程編程的FIFO實(shí)現(xiàn)。它可用于在生產(chǎn)者(producer)和消費(fèi)者(consumer)之間線(xiàn)程安全(thread-safe)地傳遞消息或其它數(shù)據(jù),因此多個(gè)線(xiàn)程可以共用同一個(gè)Queue實(shí)例。Queue的大?。ㄔ氐膫€(gè)數(shù))可用來(lái)限制內(nèi)存的使用2021-07-07基于Python實(shí)現(xiàn)剪切板實(shí)時(shí)監(jiān)控方法解析
這篇文章主要介紹了基于Python實(shí)現(xiàn)剪切板實(shí)時(shí)監(jiān)控方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09PyQt5 實(shí)現(xiàn)百度圖片下載器GUI界面
本文主要介紹了通過(guò) Pyqt5 實(shí)現(xiàn)一個(gè)界面化的下載器,在通過(guò)網(wǎng)絡(luò)請(qǐng)求實(shí)現(xiàn)各種類(lèi)型的圖片的下載。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2021-12-12