咱們要在Django項目中爲應用程序設計URL,咱們能夠建立一個名爲URLconf(一般爲urls.py)的Python模塊。
這個模塊是純Python代碼,是一個簡單的正則表達式到Python函數(視圖)之間的映射。html
這種映射關係能夠很簡短也能夠很複雜。它還能夠引用其餘的映射關係。python
若是用戶請求一個由Django提供服務的站點,它將按照如下邏輯決定執行哪些代碼:正則表達式
根URLconf
模塊。urlpatterns
,這個變量應該是一個由django.conf.urls.url()
實例組成的列表。request
。分組
捕獲的值將做爲位置參數傳遞給視圖。命名分組
捕獲的值將會以關鍵字方式傳遞給視圖,可是它能夠被直接傳參方式覆蓋。注意:shell
分組和命名分組不能同時使用。django
請求URL:http://127.0.0.1:8000/kwargs_test/123/abc/
app
url(r'^kwargs_test/(\d+)/(?P<name>\w+)/', views.kwargs_test),
視圖:框架
def kwargs_test(request, *args, **kwargs): print(args, kwargs) return HttpResponse("OK")
輸出:函數
() {'name': 'abc',}
django.conf.urls.url()的關鍵字參數會覆蓋正則表達式中命名分組捕獲的值。工具
請求URL:http://127.0.0.1:8000/kwargs_test/123/abc/
編碼
url(r'^kwargs_test/(\d+)/(?P<name>\w+)/', views.kwargs_test, {"name1": "Q1mi"}),
視圖:
def kwargs_test(request, *args, **kwargs): print(args, kwargs) return HttpResponse("OK")
輸出:
() {'name': 'abc', 'name1': 'Q1mi'}
小總結:
咱們如今掌握了三種向視圖函數傳遞參數的方法:
分組模式
從請求的URL中捕獲參數並以位置參數
的形式傳遞給視圖。命名分組模式
從請求的URL中捕獲參數並以關鍵字參數
的形式傳遞給視圖。django.conf.urls.url()
傳遞參數。在咱們的Django項目中,咱們常常會遇到要在視圖中返回一個重定向到具體URL的響應,或者要將具體的URL地址嵌入到HTML頁面中(如:a標籤的href屬性等)的狀況。
咱們以前一般都會選擇硬編碼(寫死)的方式來實現相似上述的需求,可是這並非最優的解決辦法。
例如:
在視圖函數中:
def add_student(request): if request.method == "POST": ... return redirect("/student_list/") # 將URL硬編碼到視圖中 ...
在模板文件的HTML文件中:
<a href="/student_list/">點擊查看全部學生信息</a>
Django框架充分考慮了這種需求,因此提供了工具來反向解析(推導)出具體的URL。
在Django的URLconf中,咱們能夠經過給匹配模式起別名,而後咱們能夠經過別名來反向推導出具體的URL。
例如:
在urls.py中:
urlpatterns = [ url(r'^student_list/', views.student_list, name="students"), # 爲匹配模式起別名 ... ]
在視圖中:
經過使用django.urls.reverse
根據上面的別名反向推導出URL。
from django.urls import reverse def add_student(request): if request.method == "POST": ... # 根據別名反向推導出具體的URL,避免出現硬編碼URL的狀況。 url = reverse("students") # 獲得URL: /student_list/ return redirect(url) ...
在模板語言的HTML文件中,使用下面的語法來反向推導出URL:
<a href="{% url 'students' %}">點擊查看全部學生信息</a>
當咱們的匹配模式中的正則表達式有分組或命名分組的時候該怎麼辦呢?
也就是咱們僅僅經過別名沒法推導出具體的URL時,該怎麼辦呢?
咱們能夠在反向推導URL的時候傳遞URL中須要的參數:
例如:
在urls.py中:
urlpatterns = [ # 爲匹配模式起別名,而且正則表達式中有分組匹配 url(r'^student/(\d+)', views.student_detail, name="student_detail"), ... ]
像上面的狀況,咱們就無法簡單的經過別名來推導出具體的URL。
咱們在反向推導URL的時候就須要傳遞參數了。
在視圖中:
經過使用django.urls.reverse
根據上面的別名反向推導出URL。
from django.urls import reverse def add_student(request): if request.method == "POST": ... # 根據別名和位置參數反向推導出具體的URL,避免出現硬編碼URL的狀況。 url = reverse("student_detail", args=(1,)) # 獲得URL:/student/1/ return redirect(url) ...
在模板語言的HTML文件中,使用下面的語法來反向推導出URL:
<a href="{% url 'student_detail' 1 %}">點擊查看學生詳細信息</a>
例如:
在urls.py中:
urlpatterns = [ # 爲匹配模式起別名,而且正則表達式中有分組匹配 url(r'^student/(?P<num>\d+)', views.student_detail, name="student_detail"), ... ]
像上面的狀況,咱們就無法簡單的經過別名來推導出具體的URL。
咱們在反向推導URL的時候就須要傳遞參數了。
在視圖中:
經過使用django.urls.reverse
根據上面的別名反向推導出URL。
from django.urls import reverse def add_student(request): if request.method == "POST": ... # 根據別名和位置參數反向推導出具體的URL,避免出現硬編碼URL的狀況。 url = reverse("student_detail", kwargs={"num": 10}) # 獲得URL:/student/10/ return redirect(url) ...
在模板語言的HTML文件中,使用下面的語法來反向推導出URL:
<a href="{% url 'student_detail' num=10 %}">點擊查看學生詳細信息</a>
咱們能夠爲每一個URL的匹配模式設置一個別名,而後經過別名來反向推導出URL。這樣的設置在小型項目也就是URL比較少的狀況下是徹底夠用的。
可是一旦咱們的項目比較龐大,其URL可能成百上千,不可避免的會出現別名重複的狀況。
這個時候就須要使用namespace
了,咱們能夠爲不一樣的urlpatterns
設置一個namespace
(命名空間),這樣在不一樣的命名空間下即便別名相同,仍是能夠經過namespace
來區分不一樣的URL匹配模式。
在urls.py中:
urlpatterns = [ ... # 爲app01.urls設置命名空間名:beijing url(r'^beijing/', include("app01.urls", namespace="beijing")), # 爲app02.urls設置命名空間名:shanghai url(r'^shanghai/', include("app02.urls", namespace="shanghai")), ... ]
app01/urls.py
urlpatterns = [ # app01/urls.py中有一個別名爲index的匹配模式 url(r'^index/$', views.index, name="index"), ]
app02/urls.py
urlpatterns = [ # app02/urls.py中也有一個別名爲index的匹配模式 url(r'^index/$', views.index, name="index"), ]
如今咱們就能夠經過namespace來區分上面兩個別名爲index
的匹配模式來反向推導出準確的URL了。
在視圖中:
def index(request): # 經過 namespce:name 的方式來反向推導出準確的URL url = reverse("shanghai:index") ...
在模板語言的HTML中:
<a href="{% url 'shanghai:index' %}">上海分公司首頁</a>
也能夠經過在app/urls.py中定義app_name
來設置app級別的namespace
。
例如:
在上面示例的app01/urls.py文件中:
app_name = "beijing" urlpatterns = [ url(r'^index/$', views.index, name="index"), ... ]
在這種狀況下反向推導URL的語法同上。