溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在python-django中實現(xiàn)APPEND_SLASH

發(fā)布時間:2021-06-01 18:14:28 來源:億速云 閱讀:209 作者:Leah 欄目:開發(fā)技術

本篇文章為大家展示了怎么在python-django中實現(xiàn)APPEND_SLASH,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

APPEND_SLASH 它是啥?

看變量名大概能知道做什么,就是添加斜線,用路由系統(tǒng)那里。

路由文件,只寫了路由關系代碼

......
urlpatterns = [
  url(r'^test/$', views.test),
]
......

APPEND_SLASH這個常量默認為True,就是假如你沒有添加斜線,他會幫你添加上(總體是這樣,具體得看源碼怎么寫的了)

執(zhí)行命名行代碼啟動django項目

python manage.py runserver

目前APPEND_SLASH=True,我們打開瀏覽器的開發(fā)者工具,查看網(wǎng)絡請求,輸入127.0.0.1:8000/test 這里我是沒有加斜線的

怎么在python-django中實現(xiàn)APPEND_SLASH

仔細看下網(wǎng)絡請求,我們輸入127.0.0.1:8000/test,看起來只發(fā)送了一次,其實真實發(fā)送了兩次請求。

我們繼續(xù)再訪問這個url:127.0.0.1:8000/test11,看看請求

怎么在python-django中實現(xiàn)APPEND_SLASH

我們也同樣訪問了一個url,但是這次和上面不同的是,只發(fā)送了一次請求。

兩次都是發(fā)送一個get請求,訪問服務器的一個資源。

第一次請求的url為127.0.0.1:8000/test,我們的路由關系中是沒有這個url的,對沒錯,如果訪問想要訪問到服務器的資源必須為這樣的url才行127.0.0.1:8000/test/,雖說這兩個url看起來差不多,但其實差很多的。但是第一次請求的url只需在最后加上/,就能訪問到資源了,這就是APPEND_SLASH的作用。

第二次請求的url為127.0.0.1:8000/test11,這個地址也不在我們的路由關系中,況且加上了/,也不能訪問到資源。所以總共發(fā)送了一次,最終返回了404錯誤。

先大致總結下:APPEND_SLASH=True的情況下,先會根據(jù)前端傳來的url,先檢測這個url能不能訪問資源,如果可以訪問的話,那么就去執(zhí)行相應的業(yè)務代碼,最后返回。如果這個url不能訪問到資源的話,會判斷這個url最后有沒有/,有/的話,則返回404錯誤;如果沒有/的話,便會幫你加上/,生成一個新的url,再去檢測這個新的url能不能訪問到資源,如果能訪問的話,則返回301的狀態(tài)碼,并將這個新的url傳到前端,進行重定向操作(這就是我們第一次請求出現(xiàn)的情況),如果這個新的url(幫你加上/的)還是不能訪問到資源的話,也會返回404錯誤(這就是我們第二次請求出現(xiàn)的情況)。這就是對上面出現(xiàn)情況的總結吧(具體流程還得去看源碼)

那么APPEND_SLASH=False的情況,就不會幫你加/,你前臺傳怎樣的url,那就用這個url去訪問資源,能不能訪問還得看你url對不對。

在走到路由層之前,請求會先走到中間件這一層,在這一層就執(zhí)行了上面分析的邏輯

這一個中間件實現(xiàn)了上面的邏輯 'django.middleware.common.CommonMiddleware',請求來的時候,會走這個中間件的process_request方法,下面來看這個方法寫了什么

怎么在python-django中實現(xiàn)APPEND_SLASH

看這一句注釋:# Check if a slash should be appended,檢測是否需要加上斜線

看這個方法should_redirect_with_slash,返回值為bool類型。返回True的情況是,APPEND_SLASH=True,這個url不是以/結尾的,并且這個url添加上了/,能夠訪問資源的。必須滿足這三種情況,返回值為True,其他情況的話返回就是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

就說下 is_valid_path方法有啥作用吧。你可以去看源碼具體了解

is_valid_path 檢測傳進去的url,是否能訪問到資源。(說白了就是判斷這個url是否存在我們定義的url映射中)

這樣的話,上面這段代碼就很簡單了。首先判斷APPEND_SLASH,如果為False的。那么這個方法should_redirect_with_slash直接返回False。如果APPEND_SLASH為True的話,再對請求的url進行判斷,request.path_info它的值并不是一個完整的url,而是ip+端口后面的那一部分(也就是例子中的/test),判斷它是否以斜線(/)結尾的,如果是的話,那么not request.path_info.endswith('/') 整體就為False,所以if判斷后面的表達式就為False,最終返回了False。如果不是以斜線(/)結尾的話,那么if后面的表達式就為True,那么繼續(xù)執(zhí)行條件為真的代碼塊,這個代碼塊最終返回了一個表達式的結果,這個表達式類型是這樣 bool and bool。也就是根據(jù)方法is_valid_pathd的返回值進行判斷的,如果request.path_info(代碼能分析到這里說明它不是以斜線結尾的),首先判斷這個值能不能在我們寫的路由關系映射中存不存在。存在的話,方法is_valid_path返回真,那么not True就為False,and左邊的表達式為False,整體的表達式就為False,所以最終返回的就是False。如果request.path_info的值在路由關系映射中不存在,那么and左邊的表達式為True,那就繼續(xù)看and右邊表達式的布爾值。and右邊還是調用了方法is_valid_path,只不過傳的參數(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方法的返回值,做了不同的操作。不嚴格來說,不管True還是False,最終執(zhí)行了requests.get_full_path這個方法,只不過傳入的參數(shù)不同的,最終返回了一個完整的url請求地址。

繼續(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后面的表達式為True的話,最終稿返回了一個狀態(tài)碼為301的Httpresponse對象,這個對象里帶這一個數(shù)據(jù),這個數(shù)據(jù)就是在原url基礎上加上斜線(/)的新url,前端接收到狀態(tài)碼為301的響應,則會繼續(xù)請求響應中攜帶的新地址。為False的話,返回默認返回None。

django的中間件會根據(jù)每個中間件里的process_request方法或者process_response方法不同的返回值會執(zhí)行相應的操作,具體操作不說了,不是這個知識點的內容。

那么中間件的process_request返回None的話,則會執(zhí)行下一個中間件的process_request的方法。如果返回的是HttpResponse對象的話,則不會繼續(xù)執(zhí)行下一個中間件的process_request方法,則會執(zhí)行process_response方法。具體從哪個中間件執(zhí)行和django的版本有關系,反正是不會執(zhí)行路由對應的視圖代碼的代碼,會直接返回給前端HttpResoonse對象。

好了,關于APPEND_SLASH的知識總結完畢。APPEND_SLASH它默認為True,如果想要修改的話,需要在settings.py文件中定義這個常量,賦值為False,這樣就可以覆蓋原django中配置文件里對應的常量了。至于django內部怎么操作的,下次再總結吧

最后還是補個圖吧,我把APPEND_SLASH設置為False,訪問127.0.0.1:8000/test

怎么在python-django中實現(xiàn)APPEND_SLASH

上述內容就是怎么在python-django中實現(xiàn)APPEND_SLASH,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI