Django 新手指南:如何正確編輯服務分類
更新日期: 2024 年 12 月 24 日
本文為 Django 分類功能系列教學,第 8 篇:
在 Django 應用中,編輯服務的分類是一個常見需求,用戶需要能夠查看當前服務的分類,並進行修改。
本文將帶您逐步實現這個功能,並提供視圖邏輯、模板代碼以及關鍵解析,幫助新手快速上手。
views.py
中的處理邏輯
在編輯服務時,視圖需要:
- 從資料庫中加載現有服務的資料,並傳遞給表單。
- 支持用戶提交修改後的分類數據,並更新資料庫。
以下是完整的視圖代碼範例:
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from .models import Service, Category
from .forms import ServiceForm
@login_required
def edit_service(request, id, service_id):
# 確保用戶有權限操作該服務
if not has_permission(request, id):
return redirect("services:error_page")
# 加載現有服務
service = get_object_or_404(Service, id=service_id)
if request.method == "POST":
# 綁定用戶提交的數據到表單
form = ServiceForm(request.POST, request.FILES, instance=service)
if form.is_valid():
form.save()
return redirect("services:freelancer_dashboard", id=id)
else:
# 初始化表單並帶入現有服務的數據
form = ServiceForm(instance=service)
# 傳遞所有分類以生成下拉選單
categories = Category.objects.all()
return render(request, "services/edit_service.html", {
"form": form,
"categories": categories,
})
視圖邏輯解析
- 加載服務數據:
- 使用
get_object_or_404
確保服務存在,若服務 ID 無效,將返回 404 錯誤。
- 使用
- 表單初始化:
- GET 請求:使用
instance=service
初始化表單,表單會自動填充該服務的現有數據。 - POST 請求:將用戶提交的數據與現有服務綁定,驗證並保存。
- GET 請求:使用
- 分類數據傳遞:
categories
包含所有分類,用於模板生成下拉選單選項。
模板中的下拉選單
模板負責生成用戶友好的下拉選單,並動態設置當前服務的分類為選中狀態。
以下是模板代碼範例:
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="flex flex-col space-y-2">
<label for="category" class="text-gray-700 font-medium">分類:</label>
<select
id="category"
name="category"
class="bg-white text-gray-800 border border-gray-300 rounded-md p-2 w-5/5"
>
<option value="">請選擇</option>
{% for category in categories %}
<option value="{{ category.id }}" {% if form.category.value == category.id %} selected {% endif %}>
{{ category.name }}
</option>
{% endfor %}
</select>
{% if form.category.errors %}
<p class="text-red-500 text-sm">{{ form.category.errors }}</p>
{% endif %}
</div>
<button type="submit" class="bg-blue-500 text-white rounded-md px-4 py-2">保存</button>
</form>
模板邏輯解析
- 生成分類選單:
- 使用
{% for category in categories %}
遍歷所有分類,生成<option>
選項。
- 使用
- 設置選中狀態:
- 比較
form.category.value
與category.id
,若相等,則為該選項添加selected
屬性。
- 比較
- 顯示分類錯誤:
- 若用戶未選擇分類或選擇無效分類,會在表單下方顯示錯誤訊息。
完整的邏輯解析
加載當前服務分類
在視圖中,表單會使用 instance=service
,自動將服務的現有分類,填充到表單的 category
欄位中:
form = ServiceForm(instance=service)
判斷分類選中狀態
模板中,{% if form.category.value == category.id %}
是關鍵邏輯:
form.category.value
:來自表單的當前值,即用戶之前選擇的分類 ID。category.id
:每個分類的唯一標識符。
如果二者相等,表示該分類是當前服務的分類,需設為預設選中:
<option value="{{ category.id }}" selected>
補充:關鍵邏輯拆解
form.category.value
- 這個值來自於 Django 表單中
category
欄位的當前值。- 來源:
- 如果是 GET 請求:
form.category.value
是從初始化表單時設置的instance
(例如,當前服務的分類 ID)。- 如果是 POST 請求:
form.category.value
是用戶提交的分類 ID(即 POST 數據中的值)。- 作用:反映表單當前的「分類選擇」。
category.id
- 這是來自模板中分類列表,每個分類的唯一標識符(主鍵)。
- 來源:
- 在視圖中,透過
Category.objects.all()
查詢的分類資料,每個category
物件的 ID 對應資料庫中的主鍵值。- 作用:生成
<option>
的value
屬性,標識下拉選單的選項。- 判斷條件:
{% if form.category.value == category.id %}
- 比較表單的當前分類值(
form.category.value
)與目前迴圈中分類的 ID(category.id
)。- 條件成立(相等):表示這個分類是服務當前的分類,應該在下拉選單中被預設為選中。
- 條件不成立(不相等):表示這個分類不是當前服務的分類,不應被選中。
- 結果
- 如果條件成立,在生成的 HTML 中添加
selected
屬性,讓瀏覽器預設選中該分類選項。- 如果條件不成立,不添加任何屬性,該選項處於未選中狀態。
舉例解析
假設資料庫中有以下分類:
分類名稱 分類 ID 餐飲 1 教育 2 運動 3 用戶當前編輯的服務分類為「教育」(分類 ID 為 2)。
運行邏輯
- 當
category.id = 1
時:
- 判斷條件:
form.category.value == 1
- 結果:條件不成立,生成的 HTML 為:
<option value="1">餐飲</option>
- 當
category.id = 2
時:
- 判斷條件:
form.category.value == 2
- 結果:條件成立,生成的 HTML 為:
<option value="2" selected>教育</option>
- 當
category.id = 3
時:
- 判斷條件:
form.category.value == 3
- 結果:條件不成立,生成的 HTML 為:
<option value="3">運動</option>
完整生成的下拉選單
<select> <option value="1">餐飲</option> <option value="2" selected>教育</option> <option value="3">運動</option> </select>
總結
- 目標:確保服務當前分類在下拉選單中被預設選中,讓用戶載入頁面時可以直觀地看到服務的現有分類。
- 邏輯:比較表單當前值(
form.category.value
)與分類 ID(category.id
),如果相等則加上selected
屬性。- 用戶體驗:用戶可以直觀確認現有分類,並選擇新的分類進行修改。
這樣的實現方式能夠動態適應不同的服務分類,確保編輯表單的正確性和一致性。
用戶提交表單
用戶提交修改後的分類時,表單將新的分類 ID 保存到服務的 category
欄位中:
form = ServiceForm(request.POST, request.FILES, instance=service)
if form.is_valid():
form.save()
測試場景
測試 1:載入現有服務
- 前提:服務的分類為「教育」(ID = 2)。
- 結果:頁面加載時,下拉選單會預設選中「教育」。
生成的 HTML:
<select>
<option value="">請選擇</option>
<option value="1">餐飲</option>
<option value="2" selected>教育</option>
<option value="3">運動</option>
</select>
測試 2:修改分類
- 操作:用戶將分類從「教育」改為「運動」並提交。
- 結果:服務的分類更新為「運動」(ID = 3),資料庫數據同步更新。
結論
- 視圖邏輯:
- 載入現有服務並將其傳遞給表單。
- 支持用戶提交新數據,並更新服務的分類。
- 模板邏輯:
- 動態生成分類下拉選單,根據當前服務分類設置選中狀態。
- 完整用戶流程:
- 載入編輯頁面時,顯示服務的現有分類。
- 提交後,更新分類並重定向至用戶的儀表板。
透過以上步驟,您可以實現功能完善的服務分類編輯功能,提升用戶體驗!