目錄html
咱們以前已經接觸過路由層,只是咱們可能不知道他叫這個名字,實際上在Django裏面路由層指的就是urls.py這個文件.前端
路由的概念是什麼,咱們平時生活中接觸最多的和路由有關的大概就是路由器了,那麼路由器是幹嗎的?python
路由器是鏈接多個網絡的硬件設備,在網絡之間起到網關的做用,能夠對不一樣網絡的網絡之間的數據包進行處理和轉發.正則表達式
Django裏面的路由層與此做用有些相似,路由即請求地址和視圖函數的映射關係,若是咱們把一個網站比喻成一本書的話,那麼路由就是這本書的目錄,也能夠說是索引.django
urls.py裏面配置的模板爲:後端
# urls.py from django.conf.urls import url #這裏導入url,要注意的是Django在版本爲1.x的時候是用的url,可是在版本爲2.x的時候用的是path,且用法不太同樣,2.x版本的re_path的用法是徹底繼承於url的,可是path不能,最大的區別就在於path不能用正則來匹配網址 urlpatterns = [ url(regex, view, kwargs=None, name=None), # url本質就是一個函數 ] # regex:正則表達式,用來匹配url地址的路徑部分, # 例如url地址爲:http://127.0.0.1:8001/index/,正則表達式要匹配的部分是index/ # view:一般爲一個視圖函數,用來處理業務邏輯 # 舉個栗子: urlpatterns = [ url(r'^admin/', admin.site.urls), # 系統默認的 url(r'test/$', views.test), # 嚴格正則,必須一個字不差才能進去該網頁 url(r'^$', views.home), # 網站首頁,只有網站的首頁不含任何後綴,因此一般用這種寫法來轉到網站首頁 # url(r'test/[0-9]{4}', views.test), #正則匹配,數字,且必須是四位 url(r'', views.errors) # 自定義報錯404頁面,與網站首頁不一樣,這個定義必定要放在最後面,不能放在前面,否則會阻止下方url的判斷 ] # 這裏有幾個注意事項: 1. url第一個參數是一個正則表達式 2. 一旦匹配上了,會馬上執行對應的視圖函數,再也不往下匹配 3. ^ 能夠限制其開頭,$能夠限制其結尾,這是正則匹配裏面的內容
還有一個小問題,其實有時候咱們在輸入網址的時候,沒有加最後面的左下劃線,但是網頁仍是跳轉成功了,這是由於Django裏面會有這個配置,在settings.py文件裏面,在最後咱們能夠定義一個網絡
APPEND_SLASH = False # 由於Django裏面這個值默認爲True,也就是默認會補齊,實際狀況是補上左下劃線再嘗試一次,並非補齊的概念
好比,咱們在設置過這個選項以後,在輸入如下網址 http://127.0.0.1:8000/index
app
當前,前提是你已經設置過urls以及寫了一個views函數名爲index函數
咱們能夠在網頁F12的檢查裏面的network標籤裏看到兩個請求,一個是index,一個是index/,網站
而index的請求狀態碼爲301,也就是重定向,index/的狀態碼爲200,這纔是咱們最後看到的網頁的結果
首先,分組,咱們知道分組的目的就是爲了把有相同特質的事物分到一塊兒,便於查找和管理,Django裏面也是如此的,咱們把類似內容或者格式的網頁分到一組,可讓咱們更方便的管理網頁.
那麼在分組以後咱們應該怎麼調用這些網頁呢,好比咱們在http://127.0.0.1:8000/index/
這個後綴下面創建了100個網頁,從http://127.0.0.1:8000/index/1
到http://127.0.0.1:8000/index/100
那麼難道咱們須要在urls.py裏面寫一百條語句?
非也,此時咱們分組的重要性就體現出來了.分組能夠完美解決這個問題,下面咱們就來介紹兩種分組方式,無名分組和有名分組
# 無名分組的方式大體以下 from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls),#這個是默認的,不用管 # 下述正則表達式會匹配的部分爲:index/數字/,匹配成功的分組部分會以位置參數的形式傳給視圖函數,注意,是位置參數,咱們在views.py裏面接收參數的時候要注意格式,要定義成index(request,*args) url(r'^index/(\d+)/$',views.index), ] # 這樣分組的狀況下,咱們輸入的網址,但凡前綴是http://127.0.0.1:8000/index/,後面加的一個純數字的網址,均可以匹配進入index這個函數,而後執行
#有名分組以下 # 無名分組的方式大體以下 from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls),#這個是默認的,不用管 # 匹配的方式和無名分組類似,可是,匹配成功的部分是以關鍵字參數的形式傳輸的,注意,是關鍵字參數,咱們在views.py裏面接收參數的時候要注意格式,要定義成index(request,**kwargs) url(r'^index/(?P<year>\d+)/$',views.index),# 分組,取名爲year ]
這裏要強調一點的是,有名分組和無名分組不能混合使用,也就是說同一個URL裏面,能夠有多個有名分組,也能夠有多個無名分組,可是不能同時包含有名分組和無名分組.
在說反向解析以前,咱們要知道解析的概念,在Django裏面,解析的概念就是咱們寫好後端和前端,運行起來,前端把本身的代碼翻譯出來,當別人輸入網址就自動跳轉到這個界面,大概就是解析的概念,解析的關鍵在於經過正確的路徑獲取到一個對象,或者一個網址.
那麼反向解析的概念也就出來了,反向解析就是咱們從一個別名,或者說是從一個對象來獲取到其路徑的這麼一個過程,就叫作反向解析.反向解析在Django裏面最大的便利在於咱們會給url起一個別名,而後經過這個別名來獲取路徑,這樣無論咱們url後綴怎麼改變,其他的代碼都不用隨之發生變化.
反向解析通常在三個地方會使用,即平時固定網址使用,或者在有名分組以及無名分組裏面使用.
首先,反向解析的前提是咱們要在urls.py裏面的url裏定義name屬性
# 好比咱們給編輯頁面起別名爲app01_edit # urls.py url(r'^edit_user/', views.edit_user, name='app01_edit') # 那麼咱們須要在前端,也就是html頁面裏面這麼寫 # edit_uset.html <a href="{% url 'app01_edit' %}">111</a> # 而後,咱們須要在後端,也就是views.py裏面寫 from django.shortcuts import reverse url = reverse('app01_edit') # 這樣能夠直接解析出來一個對象,此時反向解析所有完成
# 和無分組有必定的區別 # 無名分組的反向解析 # urls.py url(r'^edit_user/(\d+)/', views.edit_user, name='app01_edit') # 那麼咱們須要在前端,也就是html頁面裏面這麼寫 # edit_uset.html <a href="{% url 'app01_edit' user_obj.pk %}">111</a> # user_obj.pk 會取到該對象的主鍵 # 而後,咱們須要在後端,也就是views.py裏面寫 from django.shortcuts import reverse url = reverse('app01_edit',args=(1,))
# 有名分組的反向解析 # urls.py url(r'^edit_user/(?P<year>\d+)/', views.edit_user, name='app01_edit') # 那麼咱們須要在前端,也就是html頁面裏面這麼寫 # edit_uset.html <a href="{% url 'app01_edit' user_obj.pk %}">111</a> # 而後,咱們須要在後端,也就是views.py裏面寫 from django.shortcuts import reverse url = reverse('app01_edit',kwargs = {'key':1})
隨着項目愈來愈大,咱們的app數量也會隨之增多,此時若是全部的url都寫在項目主目錄下的urls裏,那麼這個urls.py就會十分龐大,並且工總量也很大,同時不便於管理,結構也不清晰,因此咱們提出了路由分發這麼一個概念,即每一個app都會有本身的urls.py,有本身的static,templates文件夾,這樣每一個app均可以實現本身的功能,且徹底不會影響其餘的app,因此咱們項目下的urls.py只須要做爲一箇中轉站便可,只負責將請求分發到不一樣的app中,而後由app中的urls.py完成路由與視圖函數的對應關係.
這裏咱們有一種很是簡單的執行方法
# /urls.py urlpatterns = [ url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls')) ] # 這樣咱們就能夠把須要app01執行的請求轉發給app01,須要app02執行的請求轉發給app02