跳轉至

建立 2026-09-17 更新 2026-09-17

Django Forms

官方文件:Working with formsForm and field validation

先看原生 HTML 表單的問題

在導入 Django Forms 之前,先看看純手刻表單長什麼樣子,會更容易理解 Django Forms 省下了哪些工。

GET 方法(資料會顯示在網址上,適合搜尋、篩選這類不改變伺服器狀態的操作):

<form action="/my_view/" method="get">
    <label for="your_name">Your name: </label>
    <input type="text" name="your_name">
    <input type="submit" value="OK">
</form>
def my_view(request):
    if "your_name" in request.GET and request.GET["your_name"] != "":
        return HttpResponse("Hello, " + request.GET["your_name"])
    else:
        return HttpResponse("Hello, John Doe!")

POST 方法(資料放在請求主體中,適合會改變伺服器狀態的操作,例如新增、修改資料)。注意 {% csrf_token %} 這個標籤,它是 Django 防止跨站請求偽造攻擊的機制,所有 POST 表單都必須加上

<form action="/my_view/" method="post">
    {% csrf_token %}
    <label for="your_name">Your name: </label>
    <input type="text" name="your_name">
    <input type="submit" value="OK">
</form>
def my_view(request):
    if request.POST:
        if request.POST["your_name"]:
            return HttpResponse("Hello, " + request.POST["your_name"])
        else:
            return HttpResponse("Hello, John Doe!")
    else:
        return HttpResponse("Hello, John Doe!")

可以看到即使只有一個欄位,驗證邏輯(是否為空)就得自己判斷,欄位一多,程式碼會迅速變得又長又重複。

定義 Django Form

forms.Form 定義一次欄位,Django 就能自動產生對應的 HTML、驗證資料、並提供錯誤訊息:

# forms.py
from django import forms


class NameForm(forms.Form):
    your_name = forms.CharField(label="Your name", max_length=100)

標準的 View 寫法

處理表單的 View,通常遵循「GET 顯示空表單、POST 驗證並處理資料」的固定套路:

# views.py
from django.http import HttpResponseRedirect
from django.shortcuts import render

from .forms import NameForm


def get_name(request):
    if request.method == "POST":
        # 用送出的資料建立表單實例
        form = NameForm(request.POST)
        # is_valid() 會執行所有欄位的驗證規則
        if form.is_valid():
            # 驗證通過的資料在 form.cleaned_data 裡
            # ...
            return HttpResponseRedirect("/thanks/")
    else:
        # GET 請求:顯示一個空白表單
        form = NameForm()

    return render(request, "name.html", {"form": form})

在 Template 中輸出表單

最簡單的方式是直接輸出 {{ form }},Django 會自動產生每個欄位對應的 HTML:

<!-- name.html -->
<form action="/your-name/" method="post">
    {% csrf_token %}
    {{ form }}
    <input type="submit" value="Submit">
</form>

若需要客製每個欄位的外觀(例如加 CSS class、調整排版),可以逐欄位迴圈輸出,field.errors 會顯示該欄位的驗證錯誤訊息:

{% for field in form %}
    <div class="fieldWrapper">
        {{ field.errors }}
        {{ field.label_tag }} {{ field }}
    </div>
{% endfor %}

下一步

如果表單欄位剛好對應到某個 Model,可以用 ModelForm 省掉重複定義欄位的工。