Django的路由系統
URL配置(URLconf)就像Django所支撐網站的目錄。它的本質是URL與要為該URL調用的視圖函數之間的映射表。
我們就是以這種方式告訴Django,遇到哪個URL的時候,要對應執行哪個函數。
一、URLconf配置
基本格式:
from django.conf.urls import url
urlpatterns = [
url(正則表達式,views視圖,參數,別名),
]
參數說明:
正則表達式:一個正則表達式字符串
view視圖:一個可調用對象,通常為一個視圖函數
參數:可選的要傳遞給視圖函數的默認參數【字典新式】
別名:一個可選的name參數,當動態改路勁時需用到
示例:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
請求的例子:
/articles/2005/3/ 不匹配任何url模式,因為列表中的第三個模式要求月份應該是兩個數字。
/articles/2005/ 將匹配列表中的第一個模式不是第二個,因為模式按順序匹配,第一個會首先測試是否匹配。
/articles/2005/03/ 請求將匹配列表中的第三個模式,django將調用函數views.month_archive(request,'2005','03')
注意:
Django2.0版本中的路由系統是下面的寫法(官方文檔):
from django.urls import path,re_path urlpatterns = [ path('articles/2003/', views.special_case_2003), path('articles/<int:year>/', views.year_archive), path('articles/<int:year>/<int:month>/', views.month_archive), path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail), ]
注:2.0版本中re_path和1.11版本的url用法一樣。
正則表達式詳解:
1、urlPartterns中元素按照書寫順序從上往下逐一匹配正則表達式,一旦匹配成功則不再繼續,誰在上面,就先匹配,會覆蓋下面的。
2、若要從url中捕獲一個值【即可以從url中獲取參數】,只需要在它周圍放置一對圓括號(分組匹配)。
3、不需要添加一個前導的反斜杠,因為每個url都有,例如,應該是^active/而不是^/active/。
4、每個正則表達式前面的r‘’是可選的但建議加上,以防特殊字符未轉義。
補充說明
# 是否開啟URL訪問地址后面不為/跳轉至帶有/的路徑的配置項 APPEND_SLASH=True
Django settings.py配置文件中默認沒有 APPEND_SLASH 這個參數,但 Django 默認這個參數為 APPEND_SLASH = True。 其作用就是自動在網址結尾加'/'。
其效果就是:
我們定義了urls.py:
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 時就會提示找不到頁面。
二、無名分組和命名分組
無名分組:就是正則匹配分組,圓括號包起來的部分,未指定別名,匹配完全后,將url中的匹配的括號包起來的值,以位置參數傳遞給視圖函數。
url(r'^articles/([0-9]{4})/$', views.year_archive), # 上面([0-9]{4})就是無名分組,匹配4位數字,當前端url中如輸入 http://127.0.0.1:8000/2016/ 時,2016就是匹配的值,django將會將2016以位置參數傳給后面的視圖函數 def year_archive(request,2016):pass 以用於業務邏輯
命名分組:就是給分組指定一個別名,python的正則分組命名語法為(?P<name>pattern),其中name是組的命名,pattern是匹配的模式,將url中匹配的部分以,關鍵字參數傳遞給視圖函數。
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), # 如瀏覽器中輸入:http:// 127.0.0.1:8000/articles/2016/,
django 會將匹配的2016以關鍵字分方法傳遞給視圖函數供其調用, def year_archive(request, year = ’2016‘):pass
小結:
1、urlconf匹配時,將url當成一個普通的字符串,不考慮請求方法,ip或域名,僅匹配http://www.baidu.com/index/?wd=python 着色部分。
2、捕獲的參數永遠都是字符串 ,如上面傳遞給視圖函數 views.year_archive()中的year的參數永遠是一個字符串,而不是一個數字類型。
3、視圖函數中可以指定默認值
# urls.py中 from django.conf.urls import url from . import views urlpatterns = [ url(r'^blog/$', views.page), url(r'^blog/page(?P<num>[0-9]+)/$', views.page), ] # views.py中,可以為num指定默認值 def page(request, num="1"): pass
在上面的例子中,兩個URL模式指向相同的view - views.page - 但是第一個模式並沒有從URL中捕獲任何東西。
如果第一個模式匹配上了,page()函數將使用其默認參數num=“1”,如果第二個模式匹配,page()將使用正則表達式捕獲到的num值。
4、urlconf可以傳遞額外的參數給視圖函數
URLconfs 具有一個鈎子,讓你傳遞一個Python 字典作為額外的參數傳遞給視圖函數。
django.conf.urls.url()
可以接收一個可選的第三個參數,它是一個字典,表示想要傳遞給視圖函數的額外關鍵字參數。
例如:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}), ]
在這個例子中,對於/blog/2005/請求,Django 將調用views.year_archive(request, year='2005', foo='bar')。
當傳遞額外參數的字典中的參數和URL中捕獲值的命名關鍵字參數同名時,函數調用時將使用的是字典中的參數,而不是URL中捕獲的參數。
三、Url分發
當多個應用在一個項目里時,需要用到url分發,各app管理自己的url
例如:app01、app02
1、分別在app01和app02下創建自己的urls.py【各應用下與views.py同級目錄中創建】
2、分別配置app的urls.py
app01 from django.conf.urls import url # 導入管理url的模塊 from app01 import views # 導入應用的的views urlpatterns = [ url(r'^home/[0-9]{4}/[0-9]{2}/$' ,views.app01_home)] app02 類似
3、在全局urls.py文件中導入app01及app02的urls
1、from django.conf.urls import include 2、在urlpatterns中寫入 url(r'^app01/' ,include('app01.urls')), url(r'^app02/', include('app02.urls'))
注:此時相當於app01是一級目錄,而app自己的url相當於二級目錄,當訪問時先到全局urls后到應用的urls
相當於進行字符串拼接
如:http://www.baidu.com/app01/home 會先找到app01,再去對應app下的urls中找home的url
四、命名Url和Url反向解析
官方:Django 提供一個辦法是讓URL 映射是URL 設計唯一的地方。你填充你的URLconf,然后可以雙向使用它:
- 根據用戶/瀏覽器發起的URL 請求,它調用正確的Django 視圖,並從URL 中提取它的參數需要的值。
- 根據Django 視圖的標識和將要傳遞給它的參數的值,獲取與之關聯的URL。
第一種方式就是,正向的,我們在瀏覽器種輸入地址,服務器到urls去匹配,然后執行對應的視圖函數。
第二種方式就是,反向解析url,反向url匹配,反向url查詢或簡單的url反查,如我們業務處理中redirect跳轉等。
本質:為urls.py中的url匹配規則設置別名
作用:解決當需要更新頁面或視圖函數中的url時,無需再一個個去遍歷修改,只需要再urlsconf中即urls.py中修改,視圖和模板就會自動更新url
常規
url(r'show_class/', views.show_class, name='class_list'),
無名分組
url(r'^home/([0-9]{4})/([0-9]{2})/$',views.login ,name='home')
有名分組
url(r'^home/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$',views.login ,name='home')
在views中使用
from django.shortcuts import reverse # 導入反向解析模塊
常規
def test(request): return redirect(reverse('class_list'))
無名分組
return redirect(reverse('home' , args=('1988','09'))) 上面會字符串拼接成:home/1988/09/
命名分組
return redirect(reverse("home", kwargs={"year":2018}))
在模板html中使用
語法:{% url 路徑設置的別名 %}
常規
{% url 'class_list' %}
無名分組
{% url 'home' '2018' '09' %}
有名分組
{% url 'home' '2018' '09' %} {% url 'home' month='09' year='2018' %}
命名空間模式
當多個app的url設置的別名相同時,容易出現異常報錯,在全局urls里后面的覆蓋前面的,故有下面兩個方案解決
1、在url命名前加上應用的名字 如 name = 'app_name.路徑別名'
2、在全局urls.py中導入app01時,為url也進行命名 namespace='別名,一般為應用的名字'
from django.conf.urls import url, include
url( r'app01/ ',include('app01.urls', namespace= 'app01'))
3、在app的views.py視圖函數使用
from django.shorcuts import reverse
def test(request) return redirect(reverse('app01:home', ))
4、在模板中使用
{% url 'app01:home' %}
注:如果app在全局的url指定了namesapce,那么單個app的應用url就必須也指定name,不然無法使用!!!