使用表單傳遞 GET 參數¶
開始之前¶
任務目標
在這個章節中,我們會完成:
- 了解 HTML 表單基礎
- 使用表單傳遞 GET 參數
- 在 Template 中顯示搜尋結果
HTML 表單基礎¶
HTML 表單(<form>)是網頁中收集使用者輸入的主要方式。
表單基本結構¶
<form method="get" action="/search/">
<input type="text" name="q">
<button type="submit">搜尋</button>
</form>
| 屬性 | 說明 |
|---|---|
method |
傳送方式,get 或 post |
action |
表單送出後要前往的 URL |
name |
輸入欄位的名稱,會成為參數的 key |
當使用者在輸入框輸入 django 並按下搜尋,瀏覽器會前往:
建立搜尋表單¶
步驟 1:建立 Template¶
建立 practices/templates/practices/search.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="This is my first Django Template" />
<meta name="keywords" content="Django, Template, HTML" />
<title>Search</title>
</head>
<body>
<h1>
搜尋
</h1>
<form method="get" action="">
<input type="text" name="q" placeholder="輸入關鍵字" value="{{ keyword }}" />
<button type="submit">
搜尋
</button>
</form>
{% if keyword %}
<p>
搜尋結果: {{ keyword }}
</p>
{% endif %}
</body>
</html>
action 屬性
當 action 為空字串時,表單會送到當前頁面的 URL。
步驟 2:修改 View¶
修改 practices/views.py 中的 search view,改為使用 Template:
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 render(request, "practices/search.html", {"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}")
步驟 3:測試¶
訪問 http://127.0.0.1:8000/practices/search/,你會看到一個搜尋表單。
- 在輸入框中輸入
django - 點擊「搜尋」按鈕
- 觀察網址變成
/practices/search/?q=django - 頁面顯示「搜尋結果: django」
多個輸入欄位¶
表單可以包含多個輸入欄位,每個欄位都會成為一個 GET 參數。
步驟 1:建立進階搜尋 Template¶
建立 practices/templates/practices/advanced_search.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="This is my first Django Template" />
<meta name="keywords" content="Django, Template, HTML" />
<title>Advanced Search</title>
</head>
<body>
<h1>
進階搜尋
</h1>
<form method="get" action="">
<div>
<label for="q">
關鍵字:
</label>
<input type="text" id="q" name="q" value="{{ keyword }}" />
</div>
<div>
<label for="category">
分類:
</label>
<select id="category" name="category">
<option value="all" {% if category == "all" %}selected{% endif %}>
全部
</option>
<option value="electronics"
{% if category == "electronics" %}selected{% endif %}>
電子產品
</option>
<option value="books" {% if category == "books" %}selected{% endif %}>
書籍
</option>
<option value="clothing" {% if category == "clothing" %}selected{% endif %}>
服飾
</option>
</select>
</div>
<div>
<label for="sort">
排序:
</label>
<select id="sort" name="sort">
<option value="newest" {% if sort == "newest" %}selected{% endif %}>
最新
</option>
<option value="price_asc" {% if sort == "price_asc" %}selected{% endif %}>
價格低到高
</option>
<option value="price_desc" {% if sort == "price_desc" %}selected{% endif %}>
價格高到低
</option>
</select>
</div>
<button type="submit">
搜尋
</button>
</form>
{% if keyword %}
<h2>
搜尋結果
</h2>
<p>
關鍵字: {{ keyword }}
</p>
<p>
分類: {{ category }}
</p>
<p>
排序: {{ sort }}
</p>
{% endif %}
</body>
</html>
步驟 2:建立 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 render(request, "practices/search.html", {"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}")
def advanced_search(request):
keyword = request.GET.get("q", "")
category = request.GET.get("category", "all")
sort = request.GET.get("sort", "newest")
return render(
request,
"practices/advanced_search.html",
{
"keyword": keyword,
"category": category,
"sort": sort,
},
)
步驟 3:設定 URL¶
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",
),
path("advanced-search/", views.advanced_search, name="advanced_search"),
]
步驟 4:測試¶
訪問 http://127.0.0.1:8000/practices/advanced-search/,填寫表單後送出。
觀察網址會變成類似:
Checkbox 多選範例¶
當需要讓使用者選擇多個選項時,可以使用 checkbox。
多個 checkbox 使用相同的 name 時,可以用 request.GET.getlist() 取得所有選中的值。
步驟 1:建立 Template¶
建立 practices/templates/practices/color_filter.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="This is my first Django Template" />
<meta name="keywords" content="Django, Template, HTML" />
<title>Color Filter</title>
</head>
<body>
<h1>
顏色篩選
</h1>
<form method="get" action="">
<div>
<label>
<input type="checkbox"
name="color"
value="red"
{% if "red" in colors %}checked{% endif %} />
紅色
</label>
</div>
<div>
<label>
<input type="checkbox"
name="color"
value="blue"
{% if "blue" in colors %}checked{% endif %} />
藍色
</label>
</div>
<div>
<label>
<input type="checkbox"
name="color"
value="green"
{% if "green" in colors %}checked{% endif %} />
綠色
</label>
</div>
<div>
<label>
<input type="checkbox"
name="color"
value="yellow"
{% if "yellow" in colors %}checked{% endif %} />
黃色
</label>
</div>
<button type="submit">
篩選
</button>
</form>
{% if colors %}
<h2>
篩選結果
</h2>
<p>
選擇的顏色: {{ colors|join:", " }}
</p>
{% endif %}
</body>
</html>
保持選中狀態
使用 {% if "value" in colors %}checked{% endif %} 可以在表單送出後保持 checkbox 的選中狀態。
步驟 2:建立 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 render(request, "practices/search.html", {"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}")
def advanced_search(request):
keyword = request.GET.get("q", "")
category = request.GET.get("category", "all")
sort = request.GET.get("sort", "newest")
return render(
request,
"practices/advanced_search.html",
{
"keyword": keyword,
"category": category,
"sort": sort,
},
)
def color_filter(request):
colors = request.GET.getlist("color")
return render(
request,
"practices/color_filter.html",
{"colors": colors},
)
步驟 3:設定 URL¶
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",
),
path("advanced-search/", views.advanced_search, name="advanced_search"),
path("color-filter/", views.color_filter, name="color_filter"),
]
步驟 4:測試¶
訪問 http://127.0.0.1:8000/practices/color-filter/,勾選幾個顏色後送出。
觀察網址會變成類似:
注意同一個參數名稱 color 出現了多次,這就是 getlist() 可以取得多個值的原因。
常用的表單元素¶
| 元素 | 說明 | 範例 |
|---|---|---|
<input type="text"> |
文字輸入 | <input type="text" name="q"> |
<input type="number"> |
數字輸入 | <input type="number" name="price"> |
<input type="checkbox"> |
多選框 | <input type="checkbox" name="color" value="red"> |
<input type="radio"> |
單選框 | <input type="radio" name="size" value="M"> |
<select> |
下拉選單 | <select name="category">...</select> |
<textarea> |
多行文字 | <textarea name="content"></textarea> |
任務結束¶
完成!
恭喜你完成了這個章節!現在你已經:
- 了解 HTML 表單基礎
- 使用表單傳遞 GET 參數
- 在 Template 中顯示搜尋結果