2 - django-urls路由系統基本使用

1 路由系統(urls控制)

url控制其實就是把不一樣的url對應到不一樣的views函數中去python

格式:正則表達式

# 項目目錄下的urls.py文件中

urlpatterns = [
    url(regex, view, kwargs=None, name=None)
    ... ...
]

url能夠有多個,每一個url都是一個獨立的規則。
參數以下:django

  • regex(url正則表達式):與之匹配的 URL 會執行對應的第二個參數 view。
  • view(views視圖函數): 用於執行與正則表達式匹配的 URL 請求。
  • kwargs(參數列表): 視圖使用的字典類型的參數。 --> 不多使用
  • name(別名): 用來反向獲取 URL。

1.1 正則字符串參數

url的第一個參數爲正則表達式,因此經常使用的正則表達式符號均可以進行匹配app

from user import views  # 導入咱們的app的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),  # 傳遞三個位置參數
]

這裏對url表達式使用括號,表示取出匹配到的路徑字符串(分組)函數

注意:post

  • 一旦匹配成功則再也不繼續匹配
  • 不須要添加一個前導的反斜槓,由於每一個URL 都有。例如,應該是^articles 而不是 ^/articles。
  • 每一個正則表達式前面的'r',是可選的可是建議加上。

1.2 url的分組

        在url正則表達式上加上括號,就表示對括號內的元素進行取出,而後傳給後面的views函數,根據傳遞參數的方式不一樣,分爲無名分組有名分組:url

若要從URL中捕獲一個值,只須要在它周圍放置一對圓括號。spa

1.2.1 無名分組

只須要把要分組的正則字符串用括號括起來便可。這樣,括號內的匹配的內容會看成位置參數傳遞給後面指定的views函數。code

urlpatterns = [
    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.year_month),
]
 
# ([0-9]{4}) 第一個位置參數
# ([0-9]{2}) 第二個位置參數

views函數須要定義位置參數來一一對應,不然將會拋出TypeError異常

1.2.2 有名分組

        即捕獲url中的一個值時,並賦予其名稱,使用關鍵字參數來進行傳遞。在Python 正則表達式中,命名正則表達式組的語法是(?P pattern),其中 name 是組的名稱,pattern 是要匹配的模式。

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/(?P<year>201[0-9])', user.views.index)
]

# 會把 {'year':201[0-9]} 看成關鍵字參數

這種方式能夠在views中的處理函數內,直接定義關鍵字變量來接受,而不用在乎參數的位置。

def index(request,year):
    ... ...

若是year沒有捕獲到數據,那麼views函數index將會報錯,因此咱們通常能夠在index中爲year,配置默認值來避免這種錯誤。固然也能夠在urls內,指定默認參數

url(r'^index/year(?P<year>[0-9]?)', user.views.index, {'year': 2019})

可是這樣就把前面匹配到的year的值給覆蓋了。請慎重選用

1.3 URLconf 在什麼上查找

請求的URL被看作是一個普通的Python 字符串, URLconf在其上查找並匹配。進行匹配時將不包括GET或POST請求方式的參數以及域名。

  • GET:把用戶發送的參數放在URL中進行傳遞,在URL中通常用?隔開。
  • POST:把用戶發送的參數放在請求頭中傳遞。

例如:

URLconf 不檢查使用了哪一種請求方法。換句話講,全部的請求方法,即對同一個URL的不管是 POST請求、GET請求、或是HEAD請求方法等等,都將路由到相同的函數。

1.4 include(路由分發)

        當項目中的應用變得愈來愈多的時候,若是全部的應用的URL都經過項目的urls統一進行分配,那麼耦合度會很高,另外也不利於管理,因此這裏經過include來交給應用的urls來處理。

# 項目的urls.py
from django.conf.urls import include, url
 
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^user/', include('user.urls')),
]
 
# 經過include 來指定交給那個應用的urls來處理
# include 包涵在 django.conf.urls中

在應用user下建立urls.py文件,寫入

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

urlpatterns = [
    url('^login', views.login)
]

注意:路由分發後,子路徑的起始位置就從分發的URL開始了。上面匹配到的路徑爲:user/login

1.5 別名(name參數)

當咱們在作路徑匹配而後配合form表單等須要提交的數據的元素的時候會遇到如下問題

#urls.py

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),      #  匹配路徑
]

返回的頁面文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 
 
<h1>登陸頁面</h1>
<form action="/login/" method="post">     <!--   根據路徑進行提交 -->
    <p><h2>姓名</h2></p>
    <p><input type="text" name="username"></p>
    <p><h2>密碼</h2></p>
    <p><input type="text" name="password"></p>
    <p><input type="submit" value="登陸"></p>
</form>
 
</body>
</html>

若是咱們某一天改了url匹配的路徑,那麼,就緒要修改頁面中全部的提交路徑,不然將會提交失敗.而url的name就是解決這個問題的。

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/$', views.login,name='LOGIN'),  # 添加name關鍵字
]

返回的html文件以下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 
 
<h1>登陸頁面</h1>
<form action="{% url 'LOGIN' %}" method="post">      <!-- 這裏使用name關鍵字來動態的傳遞url -->
    <p><h2>姓名</h2></p>
    <p><input type="text" name="username"></p>
    <p><h2>密碼</h2></p>
    <p><input type="text" name="password"></p>
    <p><input type="submit" value="登陸"></p>
</form>
 
</body>
</html>

這樣就算URL後期更改,也會動態指向最新的URL。

  • 我的以爲說白了就是一個變量的替換,只不過是用的是django特有的語法格式。
    name='LOGIN' 就是把前面匹配的url保存到LOGIN中,而後Django 在返回html文件的時候再進行替換。
    補充:
  • 當url存在正則表達式的時候,只使用name參數是不行的。由於正則部分沒法進行渲染。目前的解決方法是在url部分進行拼接
# --------------------------- url ---------------------------
from django.conf.urls import url
from django.contrib import admin
from app01 import views
 
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^abc/(\d+)/', views.login,name="LOGIN"),
]
 
 
 
# -------------------------- Teamplates ---------------------------
 
<form action="{% url "LOGIN" 4 %}">     # 這裏正則匹配了幾個部分,那麼就須要傳遞幾個參數
    <p>Username:</p>
    <input type="text" name="username">
    <p>Password:</p>
    <input type="text" name="password">
    <input type="submit" value="提交">
</form>

1.6 反推URL

        什麼叫反推url?在views函數中,若是想要獲取當前函數對應的url,該怎麼辦呢?還記得前面的name屬性嗎,反推url就是在views中根據name屬性的值,得到對應的url

from django.urls import reverse
 
url = reverse('name')

固然reverse還有兩個參數(args,kwargs)

args = ()
kwargs = {}
 
# 參數是配合urls中的正則表達式的
url('^detail/(\d+)' ,name='i1',views.detail)          -- >   reverse('i1',args=(10,))
# 反推的URL爲: detail/10
 
# kwargs則表示在命名關鍵字的狀況下
url('^detail/(?P<nid>\d+)' ,name='i2',views.detail)   -- >   reverse('i1',kwargs={'nid':10})
# 反推的url爲: detail/10

還有一個方法是利用request對象的path_info,由於其中存放的是用戶提交的url。

1.7 命名空間

        當在url(路由系統)中使用了include時,在views函數中,咱們就沒法單獨的利用name參數來反推url了,由於在include時,是沒法使用name關鍵字的,不過django提供了其餘關鍵字提供相似功能:namespace,稱做命名空間。

# urls.py
 
url = [
    url(r'crm/',include('crm.urls'),namespace='crm'),
    url(r'cmdb/',include('cmdb.urls'),namespace='cmdb'),
]
 
# crm 中的 urls.py
 
app_name = crm
url = [
    url(r'index/',views.index,name='index'),
]
 
# crm 中的views.py
 
def test(request):
    url = reverse('crm:index')    # 這裏經過namespace:name 來反向獲取url
    print(url)
    return HttpResponse(200)

PS:在html中,經過{% url 'crm:index' %} 也是經過namespace:name來獲取url的。

相關文章
相關標籤/搜索