[Python] Django 2.0 以 path 函式設定 urlpatterns

Django 2.0 於 2017年12月2日已經正式釋出,Django 2.0 支援 Python 3.4、3.5 以及 3.6,移除對 Python 2.7 的支援。官方強烈建議 Python 3.X 使用最新的版本。 在這次的更新中,很大的一個不同是以 path函式來設定 urlpatterns,詳情如下:

以 path 函式設定 urlpatterns

Django 2.0 專案預設建立的檔案架構如下:

from django.contrib import admin
from django.urls import path

urlpatterns = [
path('admin/', admin.site.urls),
]

我們也對照原來 Django 1.X 專案預設建立的 檔案架構:

from django.contrib import admin
from django.conf.urls import url

urlpatterns = [
url(r'^admin/', admin.site.urls),
]

Django 1.X 使用的 URL routing 語法,是以 regular expression 傳遞參數。這部分在 Django 2.0 當中改掉了,以前會把 url routing 這樣寫:

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

現在 Django 2.0 改成這樣,看起來是不是簡單多了呢?

 path('articles/<int:year>/', views.year_archive),

path 方法傳遞參數和函式對照

Django 2.0 預設的 path 方法,是採用更簡單的 URL 路由語法傳遞參數。語法:

 path(url, view, name=None)

例如:

 path('add/<int:a>/<int:b>/', add, name="myadd"),

url

url 中可以傳遞任意數量的參數給 view 中對應的函式,參數型別為字典,且前後必須加上 <> 字元,傳遞的參數會自動作型別轉換。
傳遞參數型別:

  • str:字串,匹配任何非空字符串,但不含「/」字元,這是預設值。
  • int:匹配 0 及正整數,傳回一個 int 型別。
  • slug:匹配字母、數字以及 /、 組成的字串,是 url 在最後一部分的註釋文字。
  • uuid:匹配格式化的 uuid,為了防止衝突,規定必須使用「-」字元,所有字母必須小寫。如 075194d3-6885-417e-a8a8-6c931e272f00。它會傳回一個 UUID 物件。
  • path:匹配任何非空字符串,包含路徑分隔符號「/」。

view (視圖函數)

view 指的是處理當前 url 請求的視圖函數。
Django 依序匹配每個 url 模式,一旦其中有一個模式匹配,Django 就會導入並使用 view 中對應的函式。

name (別名)

對 url 取別名,讓你能夠在 Django 的任意處,尤其是模板內可以此別名呼叫它。
這是一個非常強大的功能,相當於給 url 取了個全局變數名稱,不會將 url 匹配地址寫死。這個參數也可以省略。

例如:
from django.contrib import admin
from django.urls import path

from myapp import views

urlpatterns = [
path('articles/2018/', views.special_case_2018),
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),
]

範例

/articles/2017/06/ 將匹配第三條,並調用 views.month_archive(request, year=2017, month=6)。
/articles/2018/ 匹配第一條,並調用 views.special_case_2018(request)。
/articles/2018 將一條都匹配不上,因為它最後少了一個「/」字元,而列表中的所有模式中都以「/」結尾。
/articles/2016/05/building-a-django-site/ 將匹配第四條,並調用 views.article_detail(request, year=2016, month=5, slug=”building-a-django-site”)。

備註

  1. 捕獲到的值會自動轉換為指定類型,比如例子中的 int。
  2. 預設的情況下,捕獲到的結果為字串型別,不包含「/」這個特殊字元。
  3. 匹配模式的開頭可以不添加「/」。

書藉範例修改

我們將 「django 最強實戰」第 2 章的專案改用 path 設定,另外,我們再新增 add 網址和函式對照,網址中傳遞兩個整數型別的參數。

<urls.py>
from django.contrib import admin
from django.urls import path
from myapp.views import sayhello,hello2,hello3,hello4,add

urlpatterns = [
#使用 path 函式
path('admin/', admin.site.urls),
path('', sayhello),
path('hello/', sayhello),
path('hello2/<str:username>/',hello2),
path('hello3/<str:username>/',hello3),
path('hello4/<str:username>/',hello4,name='hello4'),
path('add/<int:a>/<int:b>/',add,name="myadd"),
]
<views.py>
from django.shortcuts import render
from django.http import HttpResponse
from datetime import datetime

#Create your views here.

def sayhello(request):
return HttpResponse("Hello Django!")

def hello2(request,username):
return HttpResponse("Hello " + username)

def hello3(request,username):
now=datetime.now()
return render(request,"hello3.html",locals())

def hello4(request,username):
now=datetime.now()
return render(request,"hello4.html",locals())

def add(request, a, b):
c = a + b
return HttpResponse(str(c))

說明

  1. http://127.0.0.1:8000 和 http://127.0.0.1:8000/hello/ 都會執行 view.sayHello(),執行結果為:「Hello Django!」。
  2. http://127.0.0.1:8000/hello2/david 會執行 view.hello2(),傳遞字串型別參數 username,內容為 david,執行結果為:「Hello david」。
  3. hello3、hello4 和 hello2 相同,也是傳遞一個字串型別參數 username,同時將 hello4 別名設定為 hello4。
  4. http://127.0.0.1:8000/add/1/5/ 會匹配 path(‘add/<int:a>/<int:b>/’, add, name=”myadd”), 並調用views.add(request, a=1, b=5)函式,執行結果為:「6」。在 view 的 add 函式中,參數 a、b 就是 int 型別,不需再作型別轉換,同時設定別名為 myadd。

使用 re_path() 方法

如果你還是懷念舊的 url routing 或是為了處理舊的 url routing 的過渡時期,你可以使用 django.urls.re_path。
使用 re_path() 方法就可以正規表示式的方式傳遞參數,使用時記得以 from django.urls import re_path 匯入 re_path 模組。

例如:以 127.0.0.1:8000 或 127.0.0.1:8000/hello/ 執行 sayhello() 函式。

<urls.py>
from django.contrib import admin
from django.urls import path,re_path
from myapp.views import sayhello

urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^$', sayhello),
re_path(r'hello/', sayhello),
]
<views.py>
from django.http import HttpResponse
def sayhello(request):
return HttpResponse("Hello Django!")

設定完成後,執行 127.0.0.1:8000 或 127.0.0.1:8000/hello/ 就會執行的 sayhello() 函式,顯示「Hello Django!」。

以 Django 1.X 的語法:url方式設定

當然我們還是可以向下相容以 Django 1.X 的語法,即 url 方式來設定。我們以「django 最強實戰」第 2 章的專案來對照。記得要以 from django.conf.urls import url 匯入模組。

<urls.py>
from django.conf.urls import url
from django.contrib import admin
from myapp.views import sayhello,hello2,hello3,hello4

urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', sayhello),
url(r'^hello/$', sayhello),
url(r'^hello2/(\w+)/$', hello2),
url(r'^hello3/(\w+)/$', hello3),
url(r'^hello4/(\w+)/$', hello4),
]
<views.py>
from django.shortcuts import render
from django.http import HttpResponse
from datetime import datetime

#Create your views here.

def sayhello(request):
return HttpResponse("Hello Django!")

def hello2(request,username):
return HttpResponse("Hello " + username)

def hello3(request,username):
now=datetime.now()
return render(request,"hello3.html",locals())

def hello4(request,username):
now=datetime.now()
return render(request,"hello4.html",locals())

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *