django 路由系統 [TOC] 路由是什麼? Django 1.11版本 URLConf官方文檔 基本格式: 示例: 參考官方文檔 2.0版本中re_path和1.11版本的url是一樣的用法。 正則表達式 詳解 補充說明 分組 命名分組 (建議使用命名分組) 小結 指定預設值 include其 ...
目錄
django 路由系統
路由是什麼?
URL配置(URLconf)就像Django所支撐網站的目錄。它的本質是URL與要為該URL調用的視圖函數之間的映射表。
我們就是以這種方式告訴Django,遇到哪個URL的時候,要對應執行哪個函數。
- 基本格式:
from django.conf.urls import url
urlpatterns = [
url(正則表達式, views視圖,參數,別名),
]
"""
正則表達式:一個正則表達式字元串
views視圖:一個可調用對象,通常為一個視圖函數
參數:可選的要傳遞給視圖函數的預設參數(字典形式)
別名:一個可選的name參數
"""
示例:
#django 1.11版本寫法
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2019/$', views.special_case_2019), #只能匹配到一個,靜態路由
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),
]
#django 2.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 urlpatterns中的元素按照書寫順序從上往下逐一匹配正則表達式,一旦匹配成功則不再繼續。
2 若要從URL中捕獲一個值,只需要在它周圍放置一對圓括弧(分組匹配)。
3 不需要添加一個前導的反斜杠,因為每個URL 都有。例如,應該是^articles 而不是 ^/articles。
4 每個正則表達式前面的'r' 是可選的但是建議加上。
5 每個表達式應該都要開始符,與結束符,讓邏輯更嚴謹 如 ^articles/$
- 補充說明
# 是否開啟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(r'^blog/([0-9]{4})/$', views.blogs), —— 》 分組 將捕獲的參數按位置傳參傳遞給視圖函數 #參數是 str類型
# views.py中,獲取分組參數
def page(request,num):
print(num) #傳的是int參數 num類型就是int 一個分組要對應有一個參數來接收傳參
return HttpResponse('ok')
命名分組 (建議使用命名分組)
url(r'^blog/(?P<year>[0-9]{4})/$', views.blogs), —— 》 命名分組 將捕獲的參數按關鍵字傳參傳遞給視圖函數
#參數類型 str 這裡的?P<year> 中的year 視圖函數也要用相同的名來獲取 year
# views.py中,獲取分組參數
def page(request,year):
print(year) #名字 要與分組名一一對應
return HttpResponse('ok')
- 小結
URLconf匹配的位置
URLconf 在請求的URL 上查找,將它當做一個普通的Python 字元串。不包括GET和POST參數以及功能變數名稱。
例如,http://www.example.com/myapp/ 請求中,URLconf 將查找 /myapp/ 。
在http://www.example.com/myapp/?page=3 請求中,URLconf 仍將查找 /myapp/ 。
URLconf 不檢查請求的方法。換句話講,所有的請求方法 —— 同一個URL的POST、GET、HEAD等等 —— 都將路由到相同的函數。
捕獲的參數永遠都是字元串
每個在URLconf中捕獲的參數都作為一個普通的Python字元串傳遞給視圖,無論正則表達式使用的是什麼匹配方式。例如,下麵這行URLconf 中:
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
傳遞到視圖函數views.year_archive() 中的year參數永遠是一個字元串類型。
指定預設值
# urls.py中
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^blog/$', views.page), #沒有傳參數,使用預設值 num = '1'
url(r'^blog/page(?P<num>[0-9]+)/$', views.page),#傳參,且 num = '0-9'任意一個數,會替換掉 num = '1'
]
# views.py中,可以為num指定預設值
def page(request, num="1"):
pass
在上面的例子中,兩個URL模式指向相同的view - views.page - 但是第一個模式並沒有從URL中捕獲任何東西。
如果第一個模式匹配上了,page()函數將使用其預設參數num=“1”,如果第二個模式匹配,page()將使用正則表達式捕獲到的num值。
include其他的URLconfs
在實際的開發環境中,我們可能需開發多個功能,有多個app以功能分劃分,需要用到路由分發,根urls負責把不同的,頁面請求,
分發到對應的app下的urls中,來執行響應程式.
- 根urls設置
- 路由分發示意:
- 註意事項
- 傳遞額外參數給視圖函數(瞭解)
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反向解析
- 官方文檔
在使用Django 項目時,一個常見的需求是獲得URL的最終形式,以用於嵌入到生成的內容中(視圖中和顯示給用戶的URL等)
或者用於處理伺服器端的導航(重定向等)。人們強烈希望不要硬編碼這些URL(費力、不可擴展且容易產生錯誤)
或者設計一種與URLconf 毫不相關的專門的URL 生成機制,因為這樣容易導致一定程度上產生過期的URL。
換句話講,需要的是一個DRY 機制。除了其它有點,它還允許設計的URL 可以自動更新而不用遍歷項目的源代碼來搜索並替換過期的URL。
獲取一個URL 最開始想到的信息是處理它視圖的標識(例如名字),查找正確的URL 的其它必要的信息有視圖參數的類型
(位置參數、關鍵字參數)和值。Django 提供一個辦法是讓URL 映射是URL 設計唯一的地方。你填充你的URLconf,然後可以雙向使用它:
根據用戶/瀏覽器發起的URL 請求,它調用正確的Django 視圖,並從URL 中提取它的參數需要的值。
根據Django 視圖的標識和將要傳遞給它的參數的值,獲取與之關聯的URL。
第一種方式是我們在前面的章節中一直討論的用法。第二種方式叫做反向解析URL、反向URL 匹配、反向URL 查詢或者簡單的URL 反查。
在需要URL 的地方,對於不同層級,Django 提供不同的工具用於URL 反查:
在模板中:使用url模板標簽。
在Python 代碼中:使用django.core.urlresolvers.reverse() 函數。
在更高層的與處理Django 模型實例相關的代碼中:使用get_absolute_url() 方法。
上面說了一大堆,你可能並沒有看懂。(那是官方文檔的生硬翻譯)。
咱們簡單來說就是可以給我們的URL匹配規則起個名字,一個URL匹配模式起一個名字。
這樣我們以後就不需要寫死URL代碼了,只需要通過名字來調用當前的URL。
- url匹配模式命名
#靜態路由
url(r'^home', views.home, name='home'), # 給我的url匹配模式起名為 home
#動態分組 路由
url(r'^index/(\d*)', views.index, name='index'), # 給我的url匹配模式起名為index
##動態命名分組 路由
url(r'^index/(?P<num>[0-9]{4})/(?P<month>\d{2})', views.index, name='index'), # 給我的url匹配模式起名為index
- 模板中引用反向解析
#靜態
{% url 'home' %} #獲取url匹配模式名為home 的完整路徑
#動態分組
{% url 'index' 2019 %} #空格後面加參數,多個參數用空格隔開,參數個數與分組數一致
#動態命名分組
{% url 'index' 2019 12 %} #順序不能錯 位置傳參
#或
{% url 'index' month=12 year=2019 %} #順序沒有要求
- 在views函數中引用反向解析
#靜態
from django.urls import reverse
reverse('home') #獲取url匹配模式名為home 的完整路徑
#動態分組
reverse("index", args=('2018', )) #一個分組的話,後面必須跟個逗號('2018',) 多個分組對應多個參數,寫在2018,後面就行('2018','06') 位置傳參
#動態命名分組
reverse("index", args=('2018','12' )) #順序不能錯 位置傳參
#或
reverse("index", kwargs={'year':'2018', 'month':'12'})
- 總結: 反向解析就是根據 url 的別名 獲取到完整的url路徑,不管url路徑怎麼修改,還是能正常獲取到完整的url路徑
命名空間模式
即使不同的APP使用相同的URL名稱,URL的命名空間模式也可以讓你唯一反轉命名的URL。
舉個例子: project中的urls.py
from django.conf.urls import url, include #導入include
urlpatterns = [
url(r'^app01/', include('app01.urls', namespace='app01')),#設置命名空間
url(r'^app02/', include('app02.urls', namespace='app02')),
]
- app01中的urls.py
from django.conf.urls import url
from app01 import views
#app_name = 'app01'
urlpatterns = [
url(r'^(?P<pk>\d+)/$', views.detail, name='detail')
]
- app02中的urls.py
from django.conf.urls import url
from app02 import views
#app_name = 'app02'
urlpatterns = [
url(r'^(?P<pk>\d+)/$', views.detail, name='detail')
]
現在,我的兩個app中 url名稱重覆了,我反轉URL的時候就可以通過命名空間的名稱得到我當前的URL。
語法:
#命名空間名稱:URL名稱
#模板中使用:
{% url 'app01:detail' pk=12 pp=99 %}
- views中的函數中使用
v = reverse('app01:detail', kwargs={'pk':11,'pp':99})
- 這樣即使app中URL的命名相同,我也可以反轉得到正確的URL了。