URL是Web服務的入口,用戶經過瀏覽器發送過來的任何請求,都是發送到一個指定的URL地址,而後被響應。php
在Django項目中編寫路由,就是向外暴露咱們接收哪些URL的請求,除此以外的任何URL都不被處理,也沒有返回。通俗地理解,不恰當的形容,URL路由是你的Web服務對外暴露的API。html
Django奉行DRY主義,提倡使用簡潔、優雅的URL,沒有.php
或.cgi
這種後綴,更不會單獨使用0、209七、1-1-192八、00這樣無心義的東西,讓你爲所欲爲設計你的URL,不受框架束縛。正則表達式
URL路由在Django項目中的體現就是urls.py
文件,這個文件能夠有不少個,但絕對不會在同一目錄下。實際上Django提倡項目有個根urls.py
,各app下分別有本身的一個urls.py
,既集中又分治,是一種解耦的模式。django
隨便新建一個Django項目,默認會自動爲咱們建立一個/project_name/urls.py
文件,而且自動包含下面的內容,這就是項目的根URL:瀏覽器
"""mysite URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.11/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import url from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), ]
前面一堆幫助性的文字,咱們不用管,關鍵是默認導入了url和admin,而後有一條指向admin後臺的url路徑。服務器
咱們本身要編寫的url路由,基本也是這個套路。app
當用戶請求一個頁面時,Django根據下面的邏輯執行操做:框架
ROOT_URLCONF
設置的值,可是若是傳入的HttpRequest對象具備urlconf屬性(由中間件設置),則其值將被用於代替ROOT_URLCONF
設置。通俗的講,就是你能夠自定義項目入口url是哪一個文件!django.conf.urls.url()
實例的一個列表。django.conf.urls.url()
的可選參數kwargs覆蓋。下面是一個簡單的 URLconf:函數
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), ]
咱們要編寫的就是上面urlpatterns列表中的一條條url,每條url,都是urlpatterns列表的一個元素。前後順序有重要關係,不能隨意擺放。最後一條的末尾建議添加一個逗號。url
urlpatterns中的每條正則表達式在第一次訪問時被自動編譯,所以其匹配速度是很是快的。
注意:
^articles
而不是^/articles
。根據上面的urlconf,下面是一些請求的例子,以及它們將匹配到的url:
/articles/2005/03/
將匹配列表中的第三個模式。Django將調用函數views.month_archive(request, '2005', '03')
。/articles/2005/3/
不匹配任何URL模式,由於列表中的第三個模式要求月份是兩個數字。/articles/2003/
將匹配列表中的第一個模式不是第二個,由於模式按順序從上往下匹配,第一個會首先被匹配。Django會調用函數views.special_case_2003(request)
/articles/2003
不匹配任何一個模式,由於每一個模式都要求URL以一個斜槓結尾。/articles/2003/03/03/
將匹配最後一個模式。Django將調用函數views.article_detail(request, '2003', '03', '03')
。不少時候,咱們須要獲取URL中的一些片斷,做爲參數,傳遞給處理請求的視圖。
上面的示例使用簡單的、沒有命名的正則表達式組(經過圓括號)來捕獲URL中的值並以位置參數的形式傳遞給視圖。
可使用命名的正則表達式組來捕獲URL中的值並以關鍵字參數傳遞給視圖。
在Python的正則表達式中,命名組的語法是(?P<name>pattern)
,其中name是組的名稱,pattern是要匹配的模式。
下面是以上URLconf使用命名組的重寫:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), ]
這個實現與前面的示例徹底相同,只有一個細微的差異:捕獲的值做爲關鍵字參數而不是位置參數傳遞給視圖函數。 像這樣:
/articles/2005/03/
請求將調用views.month_archive(request, year='2005', month='03')
函數,而不是views.month_archive(request, '2005', '03')
。/articles/2003/03/03/
請求將調用函數views.article_detail(request, year='2003', month='03', day='03')
。在實際應用中,這讓你的URLconf更加明晰且不容易產生參數順序問題的錯誤。固然,這不是強制性的,也犧牲了一些簡潔性。
針對命名組和非命名組:
請求的URL被看作是一個普通的Python字符串,URLconf在其上查找並匹配。進行匹配時將不包括GET或POST請求方式的參數以及域名。
例如,在https://www.example.com/myapp/
的請求中,URLconf將查找myapp/
。
在https://www.example.com/myapp/?page=3
的請求中,URLconf也將查找myapp/
。
URLconf不檢查使用何種HTTP請求方法,全部請求方法POST、GET、HEAD等都將路由到同一個URL的同一個視圖。在視圖中,才根據具體請求方法的不一樣,進行不一樣的處理。
每一個捕獲的參數都做爲一個普通的Python字符串傳遞給視圖,即使被捕獲的‘100’看起來像個整數,但其實是個字符串‘100’。 例如,下面這行URLconf中:
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
傳遞給views.year_archive()
的year參數將是一個字符串,不是整數,即便[0-9]{4}
只匹配整數字符串。
有一個小技巧,咱們能夠指定視圖參數的默認值。 下面是一個URLconf和視圖的示例:
# URLconf
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), ] # View (in blog/views.py) def page(request, num="1"): # Output the appropriate page of blog entries, according to num. ...
在上面的例子中,兩個URL模式指向同一個視圖views.page
。可是第一個模式不會從URL中捕獲任何值。 若是第一個模式匹配,page()函數將使用num參數的默認值"1"。 若是第二個模式匹配,page()將使用捕獲的num值。
當Django找不到與請求匹配的URL時,或者當拋出一個異常時,將調用一個錯誤處理視圖。錯誤視圖包括400、40三、404和500,分別表示請求錯誤、拒絕服務、頁面不存在和服務器錯誤。它們分別位於:
這些值能夠在根URLconf中設置。在其它app中的二級URLconf中設置這些變量無效。
Django有內置的HTML模版,用於返回錯誤頁面給用戶,可是這些403,404頁面實在醜陋,一般咱們都自定義錯誤頁面。
首先,在根URLconf中額外增長下面的條目:
# URLconf
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), ] # 增長的條目 handler400 = views.bad_request handler403 = views.permission_denied handler404 = views.page_not_found handler500 = views.page_error
而後在,views.py文件中增長四個處理視圖:
def page_not_found(request): return render(request, '404.html') def page_error(request): return render(request, '500.html') def permission_denied(request): return render(request, '403.html') def bad_request(request): return render(request, '400.html')
再根據本身的需求,建立404.html、400.html等四個頁面文件,就能夠了。