Django的URLconf

URL

概要

咱們要在Django項目中爲應用程序設計URL,咱們能夠建立一個名爲URLconf(一般爲urls.py)的Python模塊。
這個模塊是純Python代碼,是一個簡單的正則表達式到Python函數(視圖)之間的映射。html

這種映射關係能夠很簡短也能夠很複雜。它還能夠引用其餘的映射關係。python

Django如何處理一個請求

若是用戶請求一個由Django提供服務的站點,它將按照如下邏輯決定執行哪些代碼:正則表達式

  1. 一般不考慮中間件的狀況下,Django將會肯定要使用的根URLconf模塊。
  2. Django加載該Python模塊並查找變量--urlpatterns,這個變量應該是一個由django.conf.urls.url()實例組成的列表。
  3. Django按照順序遍歷每個URL模式,並停在與本次請求的URL匹配的第一個URL模式。
  4. 一旦一個正則表達式匹配上用戶請求的URL,Django就會導入並調用給定的視圖,該視圖是一個簡單的Python函數(或基於類的視圖)。
    該視圖將被傳入如下參數:
    • 一個請求示例--request
    • 正則表達式中使用分組捕獲的值將做爲位置參數傳遞給視圖。
    • 正則表達式中的命名分組捕獲的值將會以關鍵字方式傳遞給視圖,可是它能夠被直接傳參方式覆蓋。
  5. 若是沒有正則表達式匹配或者在此過程當中發生了異常,Django都會調用適當的錯誤處理視圖。

注意:shell

  1. 分組和命名分組不能同時使用。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',}
  2. 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'}

小總結:
咱們如今掌握了三種向視圖函數傳遞參數的方法:

  1. 在正則匹配模式中使用分組模式從請求的URL中捕獲參數並以位置參數的形式傳遞給視圖。
  2. 在正則匹配模式中使用命名分組模式從請求的URL中捕獲參數並以關鍵字參數的形式傳遞給視圖。
  3. 經過給django.conf.urls.url()傳遞參數。

反向解析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。

name模式

在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中須要的參數:

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>

URL中須要關鍵字參數

例如:
在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>

namespace模式

咱們能夠爲每一個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的語法同上。

相關文章
相關標籤/搜索