Path 參數¶
開始之前¶
任務目標
在這個章節中,我們會完成:
- 了解什麼是 Path 參數
- 使用 Path 參數傳遞資料
- 認識不同的參數類型
- 使用多個 Path 參數
- 了解 Path 參數和 GET 參數的使用時機
什麼是 Path 參數?¶
Path 參數是 URL 路徑的一部分,通常用於表示資源的識別。
以這個網址為例:
user001 和 12345 都是 Path 參數,它們是 URL 結構的一部分。
基本用法¶
步驟 1:建立 View¶
在 practices/views.py 中新增一個 view:
from django.http import HttpResponse
from django.shortcuts import render
def hello_world(request):
return render(request, "practices/hello.html")
def greeting(request):
name = "Django"
return render(request, "practices/greeting.html", {"name": name})
def search(request):
keyword = request.GET.get("q", "")
return HttpResponse(f"Keyword: {keyword}")
def product_list(request):
category = request.GET.get("category", "all")
sort = request.GET.get("sort", "newest")
page = request.GET.get("page", "1")
return HttpResponse(f"分類: {category}, 排序: {sort}, 頁數: {page}")
def filter_products(request):
colors = request.GET.getlist("color")
return HttpResponse(f"選擇的顏色: {', '.join(colors)}")
def hello_name(request, name):
return HttpResponse(f"Hello, {name}!")
特別注意
注意 hello_name 函式多了一個 name 參數,這個參數會從 URL 中取得。
步驟 2:設定 URL¶
在 practices/urls.py 中新增 URL pattern:
from django.urls import path
from practices import views
urlpatterns = [
path("hello/", views.hello_world, name="hello_world"),
path("greeting/", views.greeting, name="greeting"),
path("search/", views.search, name="search"),
path("products/", views.product_list, name="product_list"),
path("products/filter/", views.filter_products, name="product_filter"),
path("hello/<str:name>/", views.hello_name, name="hello_name"),
]
<str:name> 表示這是一個字串類型的參數,名稱為 name。
步驟 3:測試¶
訪問 http://127.0.0.1:8000/practices/hello/Django/ 會顯示 Hello, Django!。
試試看其他名字:
/practices/hello/Python/→Hello, Python!/practices/hello/World/→Hello, World!
Path 參數類型¶
Django 提供了幾種內建的參數類型:
| 類型 | 說明 | 匹配範例 |
|---|---|---|
str |
任何非空字串(不含 /) |
hello、my-name |
int |
正整數 | 123、1 |
slug |
ASCII 字母、數字、連字號、底線 | my-post-title |
uuid |
UUID 格式 | 075194d3-6885-417e-a8a8-6c931e272f00 |
path |
任何非空字串(含 /) |
path/to/file.txt |
使用範例¶
urlpatterns = [
# str - 預設類型,可以省略
path("users/<str:username>/", views.user_profile),
path("users/<username>/", views.user_profile), # 同上
# int - 只匹配數字
path("articles/<int:id>/", views.article_detail),
# slug - 適合用於文章標題
path("posts/<slug:title>/", views.post_detail),
# uuid - 適合用於唯一識別碼
path("orders/<uuid:order_id>/", views.order_detail),
# path - 可以包含斜線
path("files/<path:file_path>/", views.download_file),
]
注意事項
設定的型態不止被當作匹配的條件,同時會影響 view 函式收到的資料型態
多個 Path 參數¶
你可以在一個 URL 中使用多個參數:
from django.http import HttpResponse
from django.shortcuts import render
def hello_world(request):
return render(request, "practices/hello.html")
def greeting(request):
name = "Django"
return render(request, "practices/greeting.html", {"name": name})
def search(request):
keyword = request.GET.get("q", "")
return HttpResponse(f"Keyword: {keyword}")
def product_list(request):
category = request.GET.get("category", "all")
sort = request.GET.get("sort", "newest")
page = request.GET.get("page", "1")
return HttpResponse(f"分類: {category}, 排序: {sort}, 頁數: {page}")
def filter_products(request):
colors = request.GET.getlist("color")
return HttpResponse(f"選擇的顏色: {', '.join(colors)}")
def hello_name(request, name):
return HttpResponse(f"Hello, {name}!")
def article_detail(request, year, month, slug):
return HttpResponse(f"文章: {year} 年 {month} 月 - {slug}")
from django.urls import path
from practices import views
urlpatterns = [
path("hello/", views.hello_world, name="hello_world"),
path("greeting/", views.greeting, name="greeting"),
path("search/", views.search, name="search"),
path("products/", views.product_list, name="product_list"),
path("products/filter/", views.filter_products, name="product_filter"),
path("hello/<str:name>/", views.hello_name, name="hello_name"),
path(
"articles/<int:year>/<int:month>/<slug:slug>/",
views.article_detail,
name="article_detail",
),
]
訪問 http://127.0.0.1:8000/practices/articles/2024/01/my-first-post/ 會顯示:
參數名稱必須一致
URL pattern 中的參數名稱必須和 view 函式的參數名稱一致。
如果 urls.py 中定義的路徑 path("article/<int:article_id>/", views.article_detail, name="article_detail")
那 view 函式的參數名稱也必須是 article_id 才能順利匹配到
Path 參數 vs GET 參數¶
選擇指南
使用 Path 參數:
- 識別特定資源(如文章 ID、使用者名稱)
- 參數是必要的
- 參數是 URL 結構的一部分
- 範例:
/users/john/、/articles/123/
使用 GET 參數:
- 篩選、搜尋、排序、分頁
- 參數是可選的
- 參數不影響資源的識別
- 範例:
/products/?sort=price、/search/?q=django
比較範例¶
Path 參數 - 查看特定使用者 path("/users/<str:username>/", views.user_profile, name="user_profile")
因為使用者名稱為必填參數,且是特定資源的訪問,推薦使用 path 參數
GET 參數 - 搜尋使用者 path("/users/", views.user_search, name="user_search")
q 為關鍵字,可以不傳入所以推薦使用 get 參數
混合使用¶
實際應用中常常會混合使用兩種參數:
from django.http import HttpResponse
from django.shortcuts import render
def hello_world(request):
return render(request, "practices/hello.html")
def greeting(request):
name = "Django"
return render(request, "practices/greeting.html", {"name": name})
def search(request):
keyword = request.GET.get("q", "")
return HttpResponse(f"Keyword: {keyword}")
def product_list(request):
category = request.GET.get("category", "all")
sort = request.GET.get("sort", "newest")
page = request.GET.get("page", "1")
return HttpResponse(f"分類: {category}, 排序: {sort}, 頁數: {page}")
def filter_products(request):
colors = request.GET.getlist("color")
return HttpResponse(f"選擇的顏色: {', '.join(colors)}")
def hello_name(request, name):
return HttpResponse(f"Hello, {name}!")
def article_detail(request, year, month, slug):
return HttpResponse(f"文章: {year} 年 {month} 月 - {slug}")
def user_articles(request, username):
sort = request.GET.get("sort", "newest")
page = request.GET.get("page", "1")
return HttpResponse(f"{username} 的文章, 排序: {sort}, 頁數: {page}")
from django.urls import path
from practices import views
urlpatterns = [
path("hello/", views.hello_world, name="hello_world"),
path("greeting/", views.greeting, name="greeting"),
path("search/", views.search, name="search"),
path("products/", views.product_list, name="product_list"),
path("products/filter/", views.filter_products, name="product_filter"),
path("hello/<str:name>/", views.hello_name, name="hello_name"),
path(
"articles/<int:year>/<int:month>/<slug:slug>/",
views.article_detail,
name="article_detail",
),
path(
"users/<str:username>/articles/",
views.user_articles,
name="user_articles",
),
]
訪問 http://127.0.0.1:8000/practices/users/john/articles/?sort=popular&page=2 會顯示:
任務結束¶
完成!
恭喜你完成了這個章節!現在你已經:
- 了解什麼是 Path 參數
- 使用 Path 參數傳遞資料
- 認識不同的參數類型
- 使用多個 Path 參數
- 了解 Path 參數和 GET 參數的使用時機