最近在看django的官方文檔,跟着文檔敲第一個django應用,剛開始看到第一部分關於urls路由的設置時,腦子里冒出來許多問號
一時沒轉過彎來,它到底是咋轉發路由的??如何通過我配置的路徑來定位到指定視圖的?
然后自己就反復試驗了幾次,又仔細看了文檔中的描述(我的蹩腳英語不足以支撐看原版英文文檔,看的英譯漢,所以翻譯后有些字眼確實不好理解,沒內個味道了...)
OK,閑話到此為止,繼續往下看
首先,我的django項目層級如下
mysite/urls.py 是根 URLconf 文件
polls/urls.py 是一個應用下的 URLconf 文件
在 polls/urls.py
中添加了路由
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), ]
然后在 mysite/urls.py
文件的 urlpatterns
列表里插入一個 include()
from django.contrib import admin from django.urls import include, path urlpatterns = [ path('polls/', include('polls.urls')), path('admin/', admin.site.urls), ]
第一種情況
官方文檔有這樣一句話:
每當Django遇到include()時
,它都會截斷直到該時間點匹配的URL的任何部分,並將剩余的字符串發送到包含的URLconf中以進行進一步處理。
上面的這段話有2個關鍵點:截斷已經匹配到的部分、將剩下的部分繼續送給include()指定的URLconf文件
然后按照如下步驟進行分析:
- 當在瀏覽器輸入一段url,它會首先根據
mysite/urls.py
文件中 urlpatterns 包含的 path 匹配 - 例如輸入url為:http://127.0.0.1:8000/polls/,那么它會以這串url中的 polls/ 進行匹配
- 在
mysite/urls.py
文件中,發現urlpatterns
內的第一個 path 就是polls/ ,匹配成功 - 截斷這個url已經匹配的部分,所以 http://127.0.0.1:8000/polls/ 截斷后只剩下空字符串 ''
- 接下來就把空字符串 '' 繼續送給
include('polls.urls')
包含的 URLconf 文件進行處理,這里的話,就是送給投票應用 polls 自己的 URLconf 文件來繼續匹配這個剩下的空字符串 '' - 觀察
polls/urls.py
中urlpatterns
包含的 path,第一個 path 就是空字符串 '',匹配成功,所以最終這個url就映射到了這個空字符串對應的視圖 index
所以如果訪問 http://127.0.0.1:8000/polls/ 等價於訪問 http://127.0.0.1:8000/polls/ + 空字符串
第二種情況
如果上面的空字符串不好理解,可以再換個url,例如url為 http://127.0.0.1:8000/polls/test/
mysite/urls.py
內容如下
from django.contrib import admin from django.urls import include, path urlpatterns = [ path('polls/', include('polls.urls')), path('admin/', admin.site.urls), ]
polls/urls.py
中內容如下
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), path('test/', views.index2, name='index2'), # 添加了一個新路由,映射到index2視圖 ]
視圖文件 polls/views.py
添加了一個index2()函數
from django.shortcuts import render from django.http import HttpResponse # Create your views here. def index(request): return HttpResponse("hello, world") def index2(request): return HttpResponse("測試匹配路由test")
按照如下思路進行分析:
- 在瀏覽器輸入url: http://127.0.0.1:8000/polls/test/,它還是先在
mysite/urls.py
文件中以后綴“polls/test/” 匹配路由,可以發現 polls/ 匹配成功 - 截斷url后,剩下 test/ ,將其發送給投票應用 polls 的URLconf文件繼續處理,也就是
polls/urls.py
- 觀察
polls/urls.py
中urlpatterns
包含的path,第一個path
是 '',匹配失敗;第二個path是test/
,匹配成功,所以這個url就映射到了其對應的視圖,也就是 views.index2
訪問url,結果如下,確實映射到了視圖函數index2()對應的內容
第三種情況
一個django項目下可以有多個應用(app),上面的示例中只有一個應用polls
接下來再在這個項目新建一個應用,名稱為blog
然后在blog下新建一個urls.py文件
在 blog/views.py 文件中添加一個視圖
from django.shortcuts import render from django.http import HttpResponse # Create your views here. def index(request): return HttpResponse("hello, welcome to blog")
在 blog/urls.py 文件中添加path
from django.urls import path from blog import views urlpatterns = [ path('index/', views.index, name='index'), ]
然后在根urlconf文件,也就是mysite/urls.py 文件中指定blog.urls模塊
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('polls-admin/', admin.site.urls), path('polls/', include('polls.urls')), path('blog/', include('blog.urls')), # 指定blog.urls模塊 ]
這個時候如果在瀏覽器輸入 http://127.0.0.1:8000/blog/index/
根據上面的經驗,它會先定位到 blog/ ,然后到blog下的urls文件中繼續匹配 index/ ,如果匹配成功,則映射到 blog/views.py 下定義的index視圖
訪問結果如下
如果修改 blog/urls.py 文件,把path中的 index/ 改為 index2/
from django.urls import path from blog import views urlpatterns = [ path('index2/', views.index, name='index'),
]
這個時候再訪問 http://127.0.0.1:8000/blog/index/,就會報錯了,因為這個時候是 index2/ 關聯 index 視圖,而 index/ 這個路徑沒有映射(關聯)任何視圖了,此時會報404