1. 程式人生 > >Django URL(路由系統)

Django URL(路由系統)

Django URL 

Django 1.11版本 URLconf官方文件

URL配置(URLconf)就像 Django 所支撐網站的目錄。它的本質是URL模式以及要為該URL模式呼叫的檢視函式之間的對映表;就是以這種方式告訴Django,對於這個URL呼叫這段程式碼,對於那個URL呼叫那段程式碼。

 一、URLconf 

基本格式:

from django.conf.urls import url

urlpatterns = [
    url(正則表示式, views檢視函式,引數,別名),
]

引數說明:

  • 正則表示式:一個正則表示式字串
  • views檢視函式:一個可呼叫物件,通常為一個檢視函式或一個指定檢視函式路徑的字串
  • 引數:可選的要傳遞給檢視函式的預設引數(字典形式)
  • 別名:一個可選的name引數

注意

Django 2.0 版本中的路由系統已改動(官方文件

from django.urls import path

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
]

二、正則表示式說明

from django.conf.urls import url

from app_xx 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 都有。例如,應該是 ^articles 而不是 ^/articles。
  • 每個正則表示式前面的 'r'  是可選的,但是建議加上。

示例說明:

/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')

補充說明:

APPEND_SLASH=False

settings.py 配置檔案中預設沒有 APPEND_SLASH 這個引數,但 Django 預設這個引數為 APPEND_SLASH = True 其作用就是自動在網址結尾加 /

三、命名組

  上面的示例是使用簡單的正則表示式分組匹配(通過括號)來捕獲URL中的值,並將它們以位置引數形式傳遞給檢視。在更高階的用法中,可以使用命名的正則表示式組來捕獲URL位並將它們作為關鍵字引數傳遞給檢視。

在Python正則表示式中,命名正則表示式組的語法是 (?P<name>pattern) ,其中 name 是組的名稱,pattern 是要匹配的模式。

下面是以上 URLconf 使用命名組的重寫:

from django.conf.urls import url

from app_xx 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/2018/11/ 這樣呼叫檢視函式 views.month_archive(request, year="2018", month="11")

實際上,使用分組命名匹配的方式可以使 URLconf 更加明晰,且不容易產生引數順序錯誤,但一些開發人員認為分組命名組語法難看且過於冗長;至於究竟應該使用哪一種,可以根據自己的喜好來決定。

四、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字串傳遞給檢視,無論正則表示式使用的是什麼匹配方式。例如:

url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),

傳遞到檢視函式 views.year_archive() 中的 year 引數永遠是一個字串型別。

六、檢視函式中指定預設值

# urls.py中
from django.conf.urls import url

from app_xx 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模式都指向同一個檢視 views.page,但第一個模式不會從URL捕獲任何內容。如果第一個模式匹配,該 page() 函式將使用它的預設引數 num="1";如果第二個模式匹配,page() 函式將使用正則表示式捕獲的 num 值。

七、include 其他的 URLconf

比如有多個app,每個app又有自己的urls,那麼專案裡的urls就相當於一級路由,各個app下的urls相當於二級路由。

那麼各個 app 下的 urls 設定示例如下:

# app_ss/urls.py中
from django.conf.urls import url

from app_ss import views

urlpatterns = [
    url(r"^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$", views.articles),
]

專案下的 urls 設定示例如下:

from django.conf.urls import url,include

from app_ss import urls as ss_urls
from app_xx import urls as xx_urls

urlpatterns = [
    url(r'^app_ss/', include(ss_urls)),
    url(r'^app_xx/', include(xx_urls)),
]

什麼時候在路由系統中使用 include 呢?

專案裡有多個app(比如 car、house等),不同業務線使用不同的二級路由,方便管理。

示例演示:

127.0.0.1:8000/app_ss/articles/2018/10/

當訪問上面的URL時,會現在專案下的 urls.py 裡匹配 app_ss,當匹配成功時,就到 app_ss 應用下的 urls.py 裡匹配 articles/2018/10/ ,如果匹配成功,就執行檢視函式 views.articles(request, "year=2018", "month=10")

其他:

當 urlpatterns 中的正則匹配幾乎都一樣時,也可以使用 include 來刪除冗餘,如下:

八、傳遞額外的引數給檢視函式(瞭解)

URLconfs 有一個鉤子,允許一個 Python 字典作為額外的引數傳遞給檢視函式。

示例:

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^blog/(?P<year>[0-9]{4})/$', views.articles, {'foo': 'bar'}),
]

在這個例子中,對於請求 /blog/2005/ 的URL,Django將呼叫 views.articles(request, year='2005', foo='bar')

聯合框架使用此技術,可以將元資料和選項傳遞給檢視。

九、URL反向解析

簡單來說就是可以給 URL 匹配規則起個名字,一個 URL 匹配模式一個名字。這樣以後就不需要寫死 URL 程式碼了,只需要通過名字來呼叫當前的URL。

# urls.py中

urlpatterns = [ url(r"^pd_car/", views.car, name="car"), url(r"^pd_house/", views.house, name="house"), ]
# views.py中

def car(request):
    return render(request, "pd_car.html")

def house(request):
    return render(request, "pd_house.html")

還有兩個html頁面,即 pd_car.html 和 pd_house.html,在各自的 html 頁面中使用模板語法 {% url "別名" %} ,就可連結到對應的 URL 頁面中;如下面的程式碼那樣,而不是寫死的;比如,賣車頁面要跳轉到賣房頁面,寫死的格式就是這樣的 href="/pd_car/",所以不推薦這樣。

# pd_car.html中
<h1>賣車啦~~~</h1>
<a href="{% url 'house' %}">點選進入:賣房</a>

# pd_house.html中
<h1>賣房啦~~~</h1>
<a href="{% url 'car' %}">點選進入:賣車</a>

總結:給每個 url 起別名,當 A 頁面要跳轉到 B 頁面的時候,就在 A 頁面用模板語法 {% url "B的別名" %} 即可

注意

當要跳轉的 url 帶有引數的那種,比如:

url(r'^pd_car/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.car, name="car"),
url(r'^pd_house/([0-9]{4})/([0-9]{2})/$', views.house, name="house"),

那麼在 html 中也要傳遞引數(還是上面那個例子):

# pd_car.html中
<h1>賣車啦~~~</h1>
<a href="{% url "house" 2018 10 %}">點選進入:賣房</a>

# pd_house.html中
<h1>賣房啦~~~</h1>
<a href="{% url "car" year=2018 month=10 %}">點選進入:賣車</a>

views.py中也要給 url 對應的檢視函式傳遞引數,不然無法執行

def car(request,year,month):
    return render(request, "pd_car.html")

def house(request,a,b):
    return render(request, "pd_house.html")

URL名稱空間和前面的更多內容