Django 新手指南:如何正確編輯服務分類

更新日期: 2024 年 12 月 24 日

在 Django 應用中,編輯服務的分類是一個常見需求,用戶需要能夠查看當前服務的分類,並進行修改。

本文將帶您逐步實現這個功能,並提供視圖邏輯、模板代碼以及關鍵解析,幫助新手快速上手。


views.py 中的處理邏輯

在編輯服務時,視圖需要:

  1. 從資料庫中加載現有服務的資料,並傳遞給表單。
  2. 支持用戶提交修改後的分類數據,並更新資料庫。

以下是完整的視圖代碼範例:

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,
    })

視圖邏輯解析

  1. 加載服務數據
    • 使用 get_object_or_404 確保服務存在,若服務 ID 無效,將返回 404 錯誤。
  2. 表單初始化
    • GET 請求:使用 instance=service 初始化表單,表單會自動填充該服務的現有數據。
    • POST 請求:將用戶提交的數據與現有服務綁定,驗證並保存。
  3. 分類數據傳遞
    • 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>

模板邏輯解析

  1. 生成分類選單
    • 使用 {% for category in categories %} 遍歷所有分類,生成 <option> 選項。
  2. 設置選中狀態
    • 比較 form.category.valuecategory.id,若相等,則為該選項添加 selected 屬性。
  3. 顯示分類錯誤
    • 若用戶未選擇分類或選擇無效分類,會在表單下方顯示錯誤訊息。

完整的邏輯解析

加載當前服務分類

在視圖中,表單會使用 instance=service,自動將服務的現有分類,填充到表單的 category 欄位中:

form = ServiceForm(instance=service)

判斷分類選中狀態

模板中,{% if form.category.value == category.id %} 是關鍵邏輯:

  • form.category.value:來自表單的當前值,即用戶之前選擇的分類 ID。
  • category.id:每個分類的唯一標識符。

如果二者相等,表示該分類是當前服務的分類,需設為預設選中:

<option value="{{ category.id }}" selected>

補充:關鍵邏輯拆解

  1. form.category.value
    • 這個值來自於 Django 表單中 category 欄位的當前值。
    • 來源
      • 如果是 GET 請求:form.category.value 是從初始化表單時設置的 instance(例如,當前服務的分類 ID)。
      • 如果是 POST 請求:form.category.value 是用戶提交的分類 ID(即 POST 數據中的值)。
    • 作用:反映表單當前的「分類選擇」。
  2. category.id
    • 這是來自模板中分類列表,每個分類的唯一標識符(主鍵)。
    • 來源
      • 在視圖中,透過 Category.objects.all() 查詢的分類資料,每個 category 物件的 ID 對應資料庫中的主鍵值。
    • 作用:生成 <option>value 屬性,標識下拉選單的選項。
  3. 判斷條件:{% if form.category.value == category.id %}
    • 比較表單的當前分類值(form.category.value)與目前迴圈中分類的 ID(category.id)。
    • 條件成立(相等):表示這個分類是服務當前的分類,應該在下拉選單中被預設為選中。
    • 條件不成立(不相等):表示這個分類不是當前服務的分類,不應被選中。
  4. 結果
    • 如果條件成立,在生成的 HTML 中添加 selected 屬性,讓瀏覽器預設選中該分類選項。
    • 如果條件不成立,不添加任何屬性,該選項處於未選中狀態。

舉例解析

假設資料庫中有以下分類:

分類名稱分類 ID
餐飲1
教育2
運動3

用戶當前編輯的服務分類為「教育」(分類 ID 為 2)。

運行邏輯
  1. category.id = 1
    • 判斷條件:form.category.value == 1
    • 結果:條件不成立,生成的 HTML 為: <option value="1">餐飲</option>
  2. category.id = 2
    • 判斷條件:form.category.value == 2
    • 結果:條件成立,生成的 HTML 為: <option value="2" selected>教育</option>
  3. 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),資料庫數據同步更新。

結論

  1. 視圖邏輯
    • 載入現有服務並將其傳遞給表單。
    • 支持用戶提交新數據,並更新服務的分類。
  2. 模板邏輯
    • 動態生成分類下拉選單,根據當前服務分類設置選中狀態。
  3. 完整用戶流程
    • 載入編輯頁面時,顯示服務的現有分類。
    • 提交後,更新分類並重定向至用戶的儀表板。

透過以上步驟,您可以實現功能完善的服務分類編輯功能,提升用戶體驗!

Similar Posts

發佈留言

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