Django中路由的作用
URL配置(URLconf)就是Django 所支撐的網站的目錄。它的本質是URL與要爲該URL調用的視圖函數之間的映射表;你就是以這種方式告訴Django,對於客戶端發來的某個URL調用哪一段邏輯代碼對應執行
典型例子:
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
路由的基本使用
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(正則表達式, views視圖函數,參數,別名),
]
- 正則表達式:一個正則表達式字符串
- views視圖函數:一個可調用對象,通常爲一個視圖函數或一個指定視圖函數路徑的字符串
- 參數:可選的要傳遞給視圖函數的默認參數(字典形式)
- 別名:一個可選的name參數
注意:
- 若要從URL 中捕獲一個值,只需要在它周圍放置一對圓括號。
- 不需要添加一個前導的反斜槓,因爲每個URL 都有。例如,應該是^articles 而不是 ^/articles。
- 每個正則表達式前面的’r’ 是可選的但是建議加上。它告訴Python 這個字符串是“原始的”
- urlpatterns中的元素按照書寫順序從上往下逐一匹配正則表達式,一旦匹配成功則不再繼續
APPEND_SLASH
Django settings.py配置文件中默認沒有 APPEND_SLASH 這個參數,但 Django 默認這個參數爲 APPEND_SLASH = True。 其作用就是自動在網址結尾加’/’。
其效果就是:
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^blog/$', views.blog),
]
訪問 http://www.example.com/blog 時,默認將網址自動轉換爲 http://www.example/com/blog/ 。
如果在settings.py中設置了 APPEND_SLASH=False,此時我們再請求 http://www.example.com/blog 時不再向後面自動添加/,就會提示找不到頁面。
路由的分組
無名分組
# 路由層
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^blog/$', views.blog),
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
]
# 視圖層
def year_archive(request, year):
'''
year: 接收路由層傳遞過來的參數
'''
return HttpResponse('當前是%s年' % year)
上面的示例使用簡單的、沒有命名的正則表達式組(通過圓括號)來捕獲URL 中的值並以位置 參數傳遞給視圖。在更高級的用法中,可以使用命名的正則表達式組來捕獲URL 中的值並以關鍵字 參數傳遞給視圖。
無名分組分出幾個值,視圖函數就要接受幾個值(位置參數形式傳過來的)
有名分組
在Python 正則表達式中,命名正則表達式組的語法是(?Ppattern),其中name 是組的名稱,pattern 是要匹配的模式。
按照有名分組,上面的示例應該這樣寫:
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^blog/$', views.blog),
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
]
有名分組與無名分組在使用上沒有太大差別,只是有名分組對應的視圖函數的形參名字必須和分組名保持一致,也就是說,有名分組會把分出來的參數按照關鍵字參數傳遞給視圖函數,所以一定要保持名字上的一致
在實際應用中,這意味你的URLconf 會更加明晰且不容易產生參數順序問題的錯誤 —— 你可以在你的視圖函數定義中重新安排參數的順序。當然,這些好處是以簡潔爲代價。
注意:有名分組和無名分組不能混合使用
路由分發
一個Django項目裏面有多個app時,不同app的視圖層可能會有名字相同的視圖函數,爲了避免名稱衝突,我們通過路由分發的方式在總路由中進行分發,使每個app在自身內部進行路由的配置
# 導入include
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 匹配順序:匹配app01成功則相應include函數,去到app01文件夾下的urls文件中繼續匹配後續路由
url(r'^app01/', include('app01.urls')),
url(r'^app02/', include('app02.urls'))
]
# app01中的urls文件內容
from app01 import views
urlpatterns = [
url(r'^test/', views.test),
]
如果瀏覽器輸入app01/test/,就會響應到app01下views中的test取執行
反向解析(瞭解)
在視圖函數中重定向的地址如果是寫死的,url地址變更時,需要所有的url都進行修改,比較麻煩,我們可以通過反向解析,動態獲取url的地址
# 路由層
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^test/$', views.test, name='test')
]
# 視圖層
from django.shortcuts import reverse
def re_url():
url=reverse('test(url地址的別名)')
# 如果做了分組(意味着需要接受參數)
url=reverse('test(url地址的別名)',args=[],kwargs={})
return redirect(url)
{# django模板層 #}
{% url 'url地址的別名'%}
# 如果做了分組(意味着需要接受參數)
{% url 'url地址的別名' 參數1 參數2 ... 參數n %}
這樣,即使路由層中的路由更改了,我們也可以不用修改視圖層或模板層的路由地址,即便我們不應該去修改路由層中的路由。
名稱空間
路由分發時,可以指定名稱空間:
# 導入include
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/', include('app01.urls', namespace='app01')),
url(r'^app02/', include('app02.urls', namespace='app02'))
]
名稱空間可以在視圖層進行反向解析使用
不建議使用名稱空間