表單 API

關於此文件

此文件涵蓋 Django 表單 API 的詳細資訊。您應該先閱讀表單使用入門

繫結與未繫結表單

Form 實例可以是繫結到一組資料,或是未繫結

  • 如果它是繫結到一組資料,它可以驗證該資料,並將表單呈現為 HTML,並且在 HTML 中顯示資料。

  • 如果它是未繫結,則無法進行驗證(因為沒有資料可以驗證!),但仍然可以將空白表單呈現為 HTML。

class Form[原始碼]

要建立未繫結的 Form 實例,請實例化類別

>>> f = ContactForm()

要將資料繫結到表單,請將資料作為字典,當作 Form 類別建構子的第一個參數傳遞

>>> data = {
...     "subject": "hello",
...     "message": "Hi there",
...     "sender": "foo@example.com",
...     "cc_myself": True,
... }
>>> f = ContactForm(data)

在此字典中,鍵是欄位名稱,對應於 Form 類別中的屬性。值是您嘗試驗證的資料。這些通常會是字串,但並非必須是字串;您傳遞的資料類型取決於Field,我們稍後會看到。

Form.is_bound

如果您需要在執行時區分繫結和未繫結的表單實例,請檢查表單的 is_bound 屬性的值

>>> f = ContactForm()
>>> f.is_bound
False
>>> f = ContactForm({"subject": "hello"})
>>> f.is_bound
True

請注意,傳遞空的字典會建立具有空資料的繫結表單

>>> f = ContactForm({})
>>> f.is_bound
True

如果您有一個繫結的 Form 實例,並且想要以某種方式更改資料,或者您想要將未繫結的 Form 實例繫結到某些資料,請建立另一個 Form 實例。沒有方法可以更改 Form 實例中的資料。一旦建立 Form 實例,您應該將其資料視為不可變的,無論它是否有資料。

使用表單驗證資料

Form.clean()

當您必須為相互依賴的欄位新增自訂驗證時,請在您的 Form 上實作 clean() 方法。請參閱清理和驗證彼此相依的欄位,以取得範例用法。

Form.is_valid()

Form 物件的主要任務是驗證資料。對於繫結的 Form 實例,請呼叫 is_valid() 方法來執行驗證,並傳回一個布林值,指出資料是否有效

>>> data = {
...     "subject": "hello",
...     "message": "Hi there",
...     "sender": "foo@example.com",
...     "cc_myself": True,
... }
>>> f = ContactForm(data)
>>> f.is_valid()
True

讓我們嘗試一些無效的資料。在此情況下,subject 是空白的(錯誤,因為預設情況下所有欄位都是必填的),並且 sender 不是有效的電子郵件地址

>>> data = {
...     "subject": "",
...     "message": "Hi there",
...     "sender": "invalid email address",
...     "cc_myself": True,
... }
>>> f = ContactForm(data)
>>> f.is_valid()
False
Form.errors

存取 errors 屬性來取得錯誤訊息的字典

>>> f.errors
{'sender': ['Enter a valid email address.'], 'subject': ['This field is required.']}

在此字典中,鍵是欄位名稱,值是代表錯誤訊息的字串列表。錯誤訊息儲存在列表中,因為一個欄位可以有多個錯誤訊息。

您可以存取 errors,而無需先呼叫 is_valid()。當您第一次呼叫 is_valid() 或存取 errors 時,將會驗證表單的資料。

無論您存取 errors 或呼叫 is_valid() 的次數多少,驗證常式都只會被呼叫一次。這表示如果驗證有副作用,這些副作用只會觸發一次。

Form.errors.as_data()

傳回一個 dict,將欄位對應到其原始的 ValidationError 實例。

>>> f.errors.as_data()
{'sender': [ValidationError(['Enter a valid email address.'])],
'subject': [ValidationError(['This field is required.'])]}

當您需要依其 code 識別錯誤時,請隨時使用此方法。這可以啟用諸如重新撰寫錯誤訊息或在出現給定錯誤時在檢視中編寫自訂邏輯之類的操作。它也可以用來自訂格式(例如 XML)序列化錯誤;例如,as_json() 依賴於 as_data()

需要 as_data() 方法是因為回溯相容性。先前,當其呈現的錯誤訊息被新增到 Form.errors 字典時,ValidationError 實例會遺失。理想情況下,Form.errors 會儲存 ValidationError 實例,並且具有 as_ 前綴的方法可以呈現它們,但為了不破壞預期 Form.errors 中呈現錯誤訊息的程式碼,必須以其他方式進行。

Form.errors.as_json(escape_html=False)

傳回序列化為 JSON 的錯誤。

>>> f.errors.as_json()
{"sender": [{"message": "Enter a valid email address.", "code": "invalid"}],
"subject": [{"message": "This field is required.", "code": "required"}]}

預設情況下,as_json() 不會逸出其輸出。如果您將其用於像是 AJAX 請求表單視圖,而客戶端會解析回應並將錯誤插入頁面的情況,您需要確保在客戶端逸出結果,以避免跨站腳本攻擊的可能性。您可以在 JavaScript 中使用 element.textContent = errorText 或使用 jQuery 的 $(el).text(errorText) (而不是它的 .html() 函式) 來完成此操作。

如果因為某些原因您不想使用客戶端逸出,您也可以設定 escape_html=True,這樣錯誤訊息將會被逸出,您就可以直接在 HTML 中使用它們。

Form.errors.get_json_data(escape_html=False)

以適用於序列化為 JSON 的字典形式回傳錯誤。Form.errors.as_json() 回傳序列化後的 JSON,而此方法回傳的是序列化之前的錯誤資料。

escape_html 參數的行為如同在 Form.errors.as_json() 中描述的行為。

Form.add_error(field, error)

此方法允許從 Form.clean() 方法內部,或從表單外部(例如,從視圖)將錯誤新增至特定的欄位。

field 引數是要將錯誤新增至的欄位名稱。如果其值為 None,則該錯誤將被視為非欄位錯誤,如同由 Form.non_field_errors() 所回傳的錯誤。

error 引數可以是字串,或者最好是 ValidationError 的實例。有關定義表單錯誤的最佳實踐,請參閱 引發 ValidationError

請注意,Form.add_error() 會自動從 cleaned_data 中移除相關欄位。

Form.has_error(field, code=None)

此方法回傳一個布林值,表示某個欄位是否具有特定錯誤 code 的錯誤。如果 codeNone,如果該欄位包含任何錯誤,則回傳 True

若要檢查非欄位錯誤,請使用 NON_FIELD_ERRORS 作為 field 參數。

Form.non_field_errors()

此方法回傳來自 Form.errors 的錯誤列表,這些錯誤與特定欄位無關。這包括在 Form.clean() 中引發的 ValidationError 以及使用 Form.add_error(None, "...") 新增的錯誤。

未綁定表單的行為

驗證沒有資料的表單是沒有意義的,但為了記錄,以下是未綁定表單會發生的情況

>>> f = ContactForm()
>>> f.is_valid()
False
>>> f.errors
{}

初始表單值

Form.initial

使用 initial 來宣告表單欄位在執行階段的初始值。例如,您可能想要使用目前工作階段的使用者名稱填寫 username 欄位。

為了達成此目的,請使用 initial 引數到 Form。如果提供了此引數,它應該是一個字典,將欄位名稱對應到初始值。只包含您要指定初始值的欄位;沒有必要在表單中包含每個欄位。例如

>>> f = ContactForm(initial={"subject": "Hi there!"})

這些值僅會顯示在未綁定的表單中,而且如果沒有提供特定值,它們不會被用作回退值。

如果 Field 定義了 initial 並且在建立 Form 實例時包含了 initial,則後者的 initial 將具有優先權。在此範例中,initial 在欄位層級和表單實例層級都提供了,而後者具有優先權

>>> from django import forms
>>> class CommentForm(forms.Form):
...     name = forms.CharField(initial="class")
...     url = forms.URLField()
...     comment = forms.CharField()
...
>>> f = CommentForm(initial={"name": "instance"}, auto_id=False)
>>> print(f)
<div>Name:<input type="text" name="name" value="instance" required></div>
<div>Url:<input type="url" name="url" required></div>
<div>Comment:<input type="text" name="comment" required></div>
Form.get_initial_for_field(field, field_name)

回傳表單欄位的初始資料。如果存在,它會從 Form.initial 中擷取資料,否則會嘗試 Field.initial。可呼叫的值會被評估。

建議使用 BoundField.initial 而不是 get_initial_for_field(),因為 BoundField.initial 具有更簡單的介面。此外,與 get_initial_for_field() 不同,BoundField.initial 會快取其值。當處理回傳值可能變化的可呼叫物件時,這特別有用(例如 datetime.nowuuid.uuid4

>>> import uuid
>>> class UUIDCommentForm(CommentForm):
...     identifier = forms.UUIDField(initial=uuid.uuid4)
...
>>> f = UUIDCommentForm()
>>> f.get_initial_for_field(f.fields["identifier"], "identifier")
UUID('972ca9e4-7bfe-4f5b-af7d-07b3aa306334')
>>> f.get_initial_for_field(f.fields["identifier"], "identifier")
UUID('1b411fab-844e-4dec-bd4f-e9b0495f04d0')
>>> # Using BoundField.initial, for comparison
>>> f["identifier"].initial
UUID('28a09c59-5f00-4ed9-9179-a3b074fa9c30')
>>> f["identifier"].initial
UUID('28a09c59-5f00-4ed9-9179-a3b074fa9c30')

檢查哪些表單資料已變更

Form.has_changed()

當您需要檢查表單資料是否從初始資料變更時,請在您的 Form 上使用 has_changed() 方法。

>>> data = {
...     "subject": "hello",
...     "message": "Hi there",
...     "sender": "foo@example.com",
...     "cc_myself": True,
... }
>>> f = ContactForm(data, initial=data)
>>> f.has_changed()
False

當提交表單時,我們會重建它並提供原始資料,以便可以進行比較

>>> f = ContactForm(request.POST, initial=data)
>>> f.has_changed()

如果 request.POST 中的資料與 initial 中提供的資料不同,has_changed() 將會是 True,否則為 False。結果是透過對表單中的每個欄位呼叫 Field.has_changed() 來計算的。

Form.changed_data

changed_data 屬性會回傳一個列表,其中包含表單綁定資料(通常是 request.POST)中的值與 initial 中提供的資料不同的欄位名稱。如果沒有資料不同,則回傳一個空列表。

>>> f = ContactForm(request.POST, initial=data)
>>> if f.has_changed():
...     print("The following fields changed: %s" % ", ".join(f.changed_data))
...
>>> f.changed_data
['subject', 'message']

從表單存取欄位

Form.fields

您可以從 Form 實例的 fields 屬性中存取該實例的欄位

>>> for row in f.fields.values():
...     print(row)
...
<django.forms.fields.CharField object at 0x7ffaac632510>
<django.forms.fields.URLField object at 0x7ffaac632f90>
<django.forms.fields.CharField object at 0x7ffaac3aa050>
>>> f.fields["name"]
<django.forms.fields.CharField object at 0x7ffaac6324d0>

您可以變更 Form 實例的欄位和 BoundField,以變更其在表單中的呈現方式

>>> f.as_div().split("</div>")[0]
'<div><label for="id_subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="id_subject">'
>>> f["subject"].label = "Topic"
>>> f.as_div().split("</div>")[0]
'<div><label for="id_subject">Topic:</label><input type="text" name="subject" maxlength="100" required id="id_subject">'

請注意,不要更改 base_fields 屬性,因為此修改會影響同一 Python 進程中的所有後續 ContactForm 實例。

>>> f.base_fields["subject"].label_suffix = "?"
>>> another_f = ContactForm(auto_id=False)
>>> another_f.as_div().split("</div>")[0]
'<div><label for="id_subject">Subject?</label><input type="text" name="subject" maxlength="100" required id="id_subject">'

存取「清理過」的資料

Form.cleaned_data

Form 類別中的每個欄位不僅負責驗證資料,還負責「清理」資料,將其標準化為一致的格式。這是一個很好的功能,因為它允許以多種方式輸入特定欄位的資料,始終產生一致的輸出。

例如,DateField 將輸入標準化為 Python 的 datetime.date 物件。無論您傳遞的格式是 '1994-07-15' 字串、datetime.date 物件,還是其他多種格式,只要有效,DateField 都會將其標準化為 datetime.date 物件。

一旦您建立了一個具有一組資料並驗證過的 Form 實例,您就可以透過其 cleaned_data 屬性存取清理過的資料。

>>> data = {
...     "subject": "hello",
...     "message": "Hi there",
...     "sender": "foo@example.com",
...     "cc_myself": True,
... }
>>> f = ContactForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data
{'cc_myself': True, 'message': 'Hi there', 'sender': 'foo@example.com', 'subject': 'hello'}

請注意,任何基於文字的欄位(例如 CharFieldEmailField)總是將輸入清理為字串。我們將在本文件中稍後討論編碼的含義。

如果您的資料通過驗證,cleaned_data 字典只會包含有效的欄位。

>>> data = {
...     "subject": "",
...     "message": "Hi there",
...     "sender": "invalid email address",
...     "cc_myself": True,
... }
>>> f = ContactForm(data)
>>> f.is_valid()
False
>>> f.cleaned_data
{'cc_myself': True, 'message': 'Hi there'}

cleaned_data 將始終包含在 Form 中定義的欄位的鍵,即使您在定義 Form 時傳遞了額外的資料。在此範例中,我們向 ContactForm 建構函式傳遞了一堆額外的欄位,但 cleaned_data 僅包含表單的欄位。

>>> data = {
...     "subject": "hello",
...     "message": "Hi there",
...     "sender": "foo@example.com",
...     "cc_myself": True,
...     "extra_field_1": "foo",
...     "extra_field_2": "bar",
...     "extra_field_3": "baz",
... }
>>> f = ContactForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data  # Doesn't contain extra_field_1, etc.
{'cc_myself': True, 'message': 'Hi there', 'sender': 'foo@example.com', 'subject': 'hello'}

Form 有效時,cleaned_data 將包含其所有欄位的鍵和值,即使資料中沒有某些可選欄位的值。在此範例中,資料字典不包含 nick_name 欄位的值,但 cleaned_data 包含它,且值為空。

>>> from django import forms
>>> class OptionalPersonForm(forms.Form):
...     first_name = forms.CharField()
...     last_name = forms.CharField()
...     nick_name = forms.CharField(required=False)
...
>>> data = {"first_name": "John", "last_name": "Lennon"}
>>> f = OptionalPersonForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data
{'nick_name': '', 'first_name': 'John', 'last_name': 'Lennon'}

在上面的範例中,nick_namecleaned_data 值設定為空字串,因為 nick_nameCharField,而 CharField 將空值視為空字串。每個欄位類型都知道其「空白」值是什麼 – 例如,對於 DateField,它是 None 而不是空字串。有關每個欄位在此情況下的行為的完整詳細資訊,請參閱以下「內建 Field 類別」部分中每個欄位的「空值」註解。

您可以編寫程式碼來執行特定表單欄位(基於其名稱)或整個表單(考慮各種欄位的組合)的驗證。有關此的更多資訊,請參閱表單和欄位驗證

將表單輸出為 HTML

Form 物件的第二個任務是以 HTML 格式呈現自身。要執行此操作,請 print 它。

>>> f = ContactForm()
>>> print(f)
<div><label for="id_subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="id_subject"></div>
<div><label for="id_message">Message:</label><input type="text" name="message" required id="id_message"></div>
<div><label for="id_sender">Sender:</label><input type="email" name="sender" required id="id_sender"></div>
<div><label for="id_cc_myself">Cc myself:</label><input type="checkbox" name="cc_myself" id="id_cc_myself"></div>

如果表單綁定到資料,則 HTML 輸出將適當地包含該資料。例如,如果一個欄位由 <input type="text"> 表示,則資料將位於 value 屬性中。如果一個欄位由 <input type="checkbox"> 表示,則該 HTML 將在適當情況下包含 checked

>>> data = {
...     "subject": "hello",
...     "message": "Hi there",
...     "sender": "foo@example.com",
...     "cc_myself": True,
... }
>>> f = ContactForm(data)
>>> print(f)
<div><label for="id_subject">Subject:</label><input type="text" name="subject" value="hello" maxlength="100" required id="id_subject"></div>
<div><label for="id_message">Message:</label><input type="text" name="message" value="Hi there" required id="id_message"></div>
<div><label for="id_sender">Sender:</label><input type="email" name="sender" value="foo@example.com" required id="id_sender"></div>
<div><label for="id_cc_myself">Cc myself:</label><input type="checkbox" name="cc_myself" id="id_cc_myself" checked></div>

此預設輸出會用 <div> 包裹每個欄位。請注意以下事項:

  • 為了靈活性,輸出中包含 <form></form> 標籤或 <input type="submit"> 標籤。這是您的工作。

  • 每個欄位類型都有一個預設的 HTML 表示形式。CharField<input type="text"> 表示,而 EmailField<input type="email"> 表示。BooleanField(null=False)<input type="checkbox"> 表示。請注意,這些只是合理的預設值;您可以透過使用小部件來指定給定欄位要使用的 HTML,我們稍後會解釋。

  • 每個標籤的 HTML name 直接取自其在 ContactForm 類別中的屬性名稱。

  • 每個欄位的文字標籤,例如 'Subject:''Message:''Cc myself:' 是透過將所有底線轉換為空格並將第一個字母大寫,從欄位名稱產生的。同樣,請注意這些只是合理的預設值;您也可以手動指定標籤。

  • 每個文字標籤都包含在 HTML <label> 標籤中,該標籤透過其 id 指向適當的表單欄位。其 id 反過來是透過在欄位名稱前面加上 'id_' 而產生。預設情況下,輸出中包含 id 屬性和 <label> 標籤,以遵循最佳實務,但您可以變更該行為。

  • 輸出使用 HTML5 語法,目標是 <!DOCTYPE html>。例如,它使用布林屬性(例如 checked),而不是 XHTML 樣式的 checked='checked'

雖然當您 print 表單時,<div> 輸出是預設的輸出樣式,但您可以使用自己的表單範本自訂輸出,該範本可以在網站範圍、每個表單或每個實例中設定。請參閱可重複使用的表單範本

預設呈現

當您 print 表單時,預設的呈現使用以下方法和屬性。

template_name

Form.template_name

如果將表單轉換為字串(例如透過 print(form) 或在範本中透過 {{ form }}),則呈現的範本名稱。

預設情況下,一個屬性會傳回渲染器的 form_template_name 的值。您可以將其設定為字串範本名稱,以便覆寫特定表單類別的該屬性。

render()

Form.render(template_name=None, context=None, renderer=None)

render 方法由 __str__ 以及 Form.as_div()Form.as_table()Form.as_p()Form.as_ul() 方法呼叫。所有引數都是可選的,預設為

透過傳遞 template_name,您可以自訂僅用於單次呼叫的範本。

get_context()

Form.get_context()

回傳用於呈現表單的範本內容。

可用的內容如下:

  • form:已綁定的表單。

  • fields:所有已綁定的欄位,隱藏欄位除外。

  • hidden_fields:所有隱藏的已綁定欄位。

  • errors:所有非欄位相關或隱藏欄位相關的表單錯誤。

template_name_label

Form.template_name_label

用於呈現欄位 <label> 的範本,在呼叫 BoundField.label_tag()/legend_tag() 時使用。可以透過覆寫此屬性來針對每個表單變更,或者更一般地透過覆寫預設範本來變更,另請參閱 覆寫內建的表單範本

輸出樣式

變更表單輸出樣式的建議方法是設定自訂表單範本,可以是全站範圍、每個表單或每個實例。請參閱 可重複使用的表單範本 以取得範例。

提供下列輔助函式以實現向後相容性,並且是傳遞特定 template_name 值的 Form.render() 的代理。

注意

在框架提供的範本和輸出樣式中,建議使用預設的 as_div(),而不是 as_p()as_table()as_ul() 版本,因為範本會實作 <fieldset><legend> 來分組相關輸入,且更容易讓螢幕閱讀器使用者瀏覽。

每個輔助函式都會將表單方法與提供適當範本名稱的屬性配對。

as_div()

Form.template_name_div

as_div() 使用的範本。預設值:'django/forms/div.html'

Form.as_div()

as_div() 將表單呈現為一系列 <div> 元素,每個 <div> 包含一個欄位,例如

>>> f = ContactForm()
>>> f.as_div()

… 會產生類似以下的 HTML

<div>
<label for="id_subject">Subject:</label>
<input type="text" name="subject" maxlength="100" required id="id_subject">
</div>
<div>
<label for="id_message">Message:</label>
<input type="text" name="message" required id="id_message">
</div>
<div>
<label for="id_sender">Sender:</label>
<input type="email" name="sender" required id="id_sender">
</div>
<div>
<label for="id_cc_myself">Cc myself:</label>
<input type="checkbox" name="cc_myself" id="id_cc_myself">
</div>

as_p()

Form.template_name_p

as_p() 使用的範本。預設值:'django/forms/p.html'

Form.as_p()

as_p() 將表單呈現為一系列 <p> 標籤,每個 <p> 包含一個欄位

>>> f = ContactForm()
>>> f.as_p()
'<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required></p>\n<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required></p>\n<p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" required></p>\n<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></p>'
>>> print(f.as_p())
<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required></p>
<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required></p>
<p><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required></p>
<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></p>

as_ul()

Form.template_name_ul

as_ul() 使用的範本。預設值:'django/forms/ul.html'

Form.as_ul()

as_ul() 將表單呈現為一系列 <li> 標籤,每個 <li> 包含一個欄位。它不包含 <ul></ul>,以便您可以在 <ul> 上指定任何 HTML 屬性以實現彈性。

>>> f = ContactForm()
>>> f.as_ul()
'<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required></li>\n<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required></li>\n<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required></li>\n<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></li>'
>>> print(f.as_ul())
<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required></li>
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required></li>
<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required></li>
<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></li>

as_table()

Form.template_name_table

as_table() 使用的範本。預設值:'django/forms/table.html'

Form.as_table()

as_table() 將表單呈現為 HTML <table>

>>> f = ContactForm()
>>> f.as_table()
'<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" required></td></tr>\n<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" required></td></tr>\n<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" required></td></tr>\n<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself"></td></tr>'
>>> print(f.as_table())
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" required></td></tr>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" required></td></tr>
<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" required></td></tr>
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself"></td></tr>

設定必要或錯誤表單列的樣式

Form.error_css_class
Form.required_css_class

設定必要或有錯誤的表單列和欄位的樣式是很常見的。例如,您可能想要以粗體呈現必要的表單列,並以紅色醒目提示錯誤。

Form 類別有一些勾點,可用於將 class 屬性新增至必要的列或有錯誤的列:設定 Form.error_css_class 和/或 Form.required_css_class 屬性

from django import forms


class ContactForm(forms.Form):
    error_css_class = "error"
    required_css_class = "required"

    # ... and the rest of your fields here

完成後,將會根據需要為列提供 "error" 和/或 "required" 類別。HTML 看起來會像這樣

>>> f = ContactForm(data)
>>> print(f)
<div class="required"><label for="id_subject" class="required">Subject:</label> ...
<div class="required"><label for="id_message" class="required">Message:</label> ...
<div class="required"><label for="id_sender" class="required">Sender:</label> ...
<div><label for="id_cc_myself">Cc myself:</label> ...
>>> f["subject"].label_tag()
<label class="required" for="id_subject">Subject:</label>
>>> f["subject"].legend_tag()
<legend class="required" for="id_subject">Subject:</legend>
>>> f["subject"].label_tag(attrs={"class": "foo"})
<label for="id_subject" class="foo required">Subject:</label>
>>> f["subject"].legend_tag(attrs={"class": "foo"})
<legend for="id_subject" class="foo required">Subject:</legend>

設定表單元素的 HTML id 屬性和 <label> 標籤

Form.auto_id

預設情況下,表單呈現方法包含

  • 表單元素上的 HTML id 屬性。

  • 標籤周圍的對應 <label> 標籤。HTML <label> 標籤指定哪個標籤文字與哪個表單元素關聯。此小改進使表單更易於使用,並更容易讓輔助裝置存取。使用 <label> 標籤始終是一個好主意。

id 屬性值是透過將 id_ 前置於表單欄位名稱來產生的。如果您想要變更 id 慣例,或完全移除 HTML id 屬性和 <label> 標籤,則此行為是可設定的。

使用 Form 建構函式的 auto_id 引數來控制 id 和標籤行為。此引數必須為 TrueFalse 或字串。

如果 auto_idFalse,則表單輸出將不包含 <label> 標籤,也不會包含 id 屬性。

>>> f = ContactForm(auto_id=False)
>>> print(f)
<div>Subject:<input type="text" name="subject" maxlength="100" required></div>
<div>Message:<textarea name="message" cols="40" rows="10" required></textarea></div>
<div>Sender:<input type="email" name="sender" required></div>
<div>Cc myself:<input type="checkbox" name="cc_myself"></div>

如果 auto_id 設定為 True,則表單輸出包含 <label> 標籤,並將使用欄位名稱作為每個表單欄位的 id

>>> f = ContactForm(auto_id=True)
>>> print(f)
<div><label for="subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="subject"></div>
<div><label for="message">Message:</label><textarea name="message" cols="40" rows="10" required id="message"></textarea></div>
<div><label for="sender">Sender:</label><input type="email" name="sender" required id="sender"></div>
<div><label for="cc_myself">Cc myself:</label><input type="checkbox" name="cc_myself" id="cc_myself"></div>

如果 auto_id 設定為包含格式字元 '%s' 的字串,則表單輸出將包含 <label> 標籤,並將根據格式字串產生 id 屬性。例如,對於格式字串 'field_%s',名為 subject 的欄位將獲得 'field_subject'id 值。繼續我們的範例

>>> f = ContactForm(auto_id="id_for_%s")
>>> print(f)
<div><label for="id_for_subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="id_for_subject"></div>
<div><label for="id_for_message">Message:</label><textarea name="message" cols="40" rows="10" required id="id_for_message"></textarea></div>
<div><label for="id_for_sender">Sender:</label><input type="email" name="sender" required id="id_for_sender"></div>
<div><label for="id_for_cc_myself">Cc myself:</label><input type="checkbox" name="cc_myself" id="id_for_cc_myself"></div>

如果 auto_id 設定為任何其他真值(例如不包含 %s 的字串),則程式庫的行為會如同 auto_idTrue

預設情況下,auto_id 設定為字串 'id_%s'

Form.label_suffix

一個可翻譯的字串(在英文中預設為冒號 (:)),當表單呈現時,將附加在任何標籤名稱之後。

可以使用 label_suffix 參數來自訂該字元,或完全省略它。

>>> f = ContactForm(auto_id="id_for_%s", label_suffix="")
>>> print(f)
<div><label for="id_for_subject">Subject</label><input type="text" name="subject" maxlength="100" required id="id_for_subject"></div>
<div><label for="id_for_message">Message</label><textarea name="message" cols="40" rows="10" required id="id_for_message"></textarea></div>
<div><label for="id_for_sender">Sender</label><input type="email" name="sender" required id="id_for_sender"></div>
<div><label for="id_for_cc_myself">Cc myself</label><input type="checkbox" name="cc_myself" id="id_for_cc_myself"></div>
>>> f = ContactForm(auto_id="id_for_%s", label_suffix=" ->")
>>> print(f)
<div><label for="id_for_subject">Subject -&gt;</label><input type="text" name="subject" maxlength="100" required id="id_for_subject"></div>
<div><label for="id_for_message">Message -&gt;</label><textarea name="message" cols="40" rows="10" required id="id_for_message"></textarea></div>
<div><label for="id_for_sender">Sender -&gt;</label><input type="email" name="sender" required id="id_for_sender"></div>
<div><label for="id_for_cc_myself">Cc myself -&gt;</label><input type="checkbox" name="cc_myself" id="id_for_cc_myself"></div>

請注意,僅當標籤的最後一個字元不是標點符號字元(在英文中,這些是 .!?:)時,才會新增標籤後綴。

欄位也可以定義自己的 label_suffix。這將優先於 Form.label_suffix。也可以在執行時使用 label_suffix 參數來覆寫後綴,方法是使用 label_tag()/legend_tag()

Form.use_required_attribute

當設定為 True (預設值) 時,必填的表單欄位將具有 required HTML 屬性。

表單集合 會以 use_required_attribute=False 來實例化表單,以避免在從表單集合中新增和刪除表單時發生不正確的瀏覽器驗證。

設定表單小工具的呈現方式

Form.default_renderer

指定用於表單的渲染器。預設值為 None,這表示使用 FORM_RENDERER 設定所指定的預設渲染器。

您可以在宣告表單時將其設定為類別屬性,或使用 Form.__init__()renderer 引數。例如

from django import forms


class MyForm(forms.Form):
    default_renderer = MyRenderer()

form = MyForm(renderer=MyRenderer())

關於欄位順序的注意事項

as_p()as_ul()as_table() 快捷方式中,欄位會按照您在表單類別中定義它們的順序顯示。例如,在 ContactForm 範例中,欄位會按照 subjectmessagesendercc_myself 的順序定義。若要重新排列 HTML 輸出,請變更這些欄位在類別中列出的順序。

還有其他幾種方法可以自訂順序

Form.field_order

預設情況下,Form.field_order=None,這會保留您在表單類別中定義欄位的順序。如果 field_order 是欄位名稱的清單,則欄位會按照清單指定的順序排列,其餘欄位會根據預設順序附加。清單中未知的欄位名稱會被忽略。這使得可以通過將其設定為 None 來停用子類別中的欄位,而無需重新定義順序。

您也可以使用 FormForm.field_order 引數來覆寫欄位順序。如果 Form 定義了 field_order並且您在實例化 Form 時包含 field_order,則後者的 field_order 將具有優先權。

Form.order_fields(field_order)

您可以隨時使用 order_fields() 重新排列欄位,並使用欄位名稱清單,如 field_order 中所示。

錯誤的顯示方式

如果您呈現已繫結的 Form 物件,則呈現的動作會自動執行表單的驗證(如果尚未發生),並且 HTML 輸出將在欄位附近包含驗證錯誤,作為 <ul class="errorlist">。錯誤訊息的特定位置取決於您使用的輸出方法。

>>> data = {
...     "subject": "",
...     "message": "Hi there",
...     "sender": "invalid email address",
...     "cc_myself": True,
... }
>>> f = ContactForm(data, auto_id=False)
>>> print(f)
<div>Subject:
  <ul class="errorlist"><li>This field is required.</li></ul>
  <input type="text" name="subject" maxlength="100" required aria-invalid="true">
</div>
<div>Message:
  <textarea name="message" cols="40" rows="10" required>Hi there</textarea>
</div>
<div>Sender:
  <ul class="errorlist"><li>Enter a valid email address.</li></ul>
  <input type="email" name="sender" value="invalid email address" required aria-invalid="true">
</div>
<div>Cc myself:
  <input type="checkbox" name="cc_myself" checked>
</div>

自訂錯誤清單格式

class ErrorList(initlist=None, error_class=None, renderer=None)[原始碼]

預設情況下,表單會使用 django.forms.utils.ErrorList 來格式化驗證錯誤。ErrorList 是一個類似清單的物件,其中 initlist 是錯誤的清單。此外,此類別還具有下列屬性和方法。

error_class

呈現錯誤清單時要使用的 CSS 類別。任何提供的類別都會新增至預設的 errorlist 類別。

renderer

指定用於 ErrorList渲染器。預設值為 None,這表示使用 FORM_RENDERER 設定所指定的預設渲染器。

template_name

當呼叫 __str__render() 時所使用的範本名稱。預設值為 'django/forms/errors/list/default.html',它是 'ul.html' 範本的代理。

template_name_text

當呼叫 as_text() 時所使用的範本名稱。預設值為 'django/forms/errors/list/text.html'。此範本會將錯誤呈現為項目符號清單。

template_name_ul

當呼叫 as_ul() 時所使用的範本名稱。預設值為 'django/forms/errors/list/ul.html'。此範本會將錯誤呈現在 <li> 標籤中,並使用由 error_class 定義的 CSS 類別包裹在 <ul> 中。

get_context()[原始碼]

傳回範本中呈現錯誤的上下文。

可用的內容如下:

  • errors:錯誤的列表。

  • error_class:CSS 類別的字串。

render(template_name=None, context=None, renderer=None)

render 方法會被 __str__ 以及 as_ul() 方法呼叫。

所有參數都是可選的,預設值如下:

as_text()

使用由 template_name_text 定義的範本呈現錯誤列表。

as_ul()

使用由 template_name_ul 定義的範本呈現錯誤列表。

如果您想自訂錯誤的呈現方式,可以覆寫 template_name 屬性,或者更普遍地說,覆寫預設範本,另請參閱 覆寫內建表單範本

更精細的輸出

as_p()as_ul()as_table() 方法是快捷方式,它們並非顯示表單物件的唯一方式。

class BoundField[原始碼]

用於顯示 HTML 或存取 Form 實例的單一欄位的屬性。

此物件的 __str__() 方法會顯示此欄位的 HTML。

若要檢索單一的 BoundField,請使用表單上的字典查找語法,並以欄位的名稱作為鍵。

>>> form = ContactForm()
>>> print(form["subject"])
<input id="id_subject" type="text" name="subject" maxlength="100" required>

若要檢索所有 BoundField 物件,請迭代表單。

>>> form = ContactForm()
>>> for boundfield in form:
...     print(boundfield)
...
<input id="id_subject" type="text" name="subject" maxlength="100" required>
<input type="text" name="message" id="id_message" required>
<input type="email" name="sender" id="id_sender" required>
<input type="checkbox" name="cc_myself" id="id_cc_myself">

欄位特定的輸出會遵循表單物件的 auto_id 設定。

>>> f = ContactForm(auto_id=False)
>>> print(f["message"])
<input type="text" name="message" required>
>>> f = ContactForm(auto_id="id_%s")
>>> print(f["message"])
<input type="text" name="message" id="id_message" required>

BoundField 的屬性

BoundField.auto_id[原始碼]

BoundField 的 HTML ID 屬性。如果 Form.auto_idFalse,則傳回空字串。

BoundField.data[原始碼]

此屬性會傳回此 BoundField 的資料,這些資料由 widget 的 value_from_datadict() 方法擷取,如果未提供則為 None

>>> unbound_form = ContactForm()
>>> print(unbound_form["subject"].data)
None
>>> bound_form = ContactForm(data={"subject": "My Subject"})
>>> print(bound_form["subject"].data)
My Subject
BoundField.errors[原始碼]

一個 類列表物件,在列印時會顯示為 HTML <ul class="errorlist">

>>> data = {"subject": "hi", "message": "", "sender": "", "cc_myself": ""}
>>> f = ContactForm(data, auto_id=False)
>>> print(f["message"])
<input type="text" name="message" required aria-invalid="true">
>>> f["message"].errors
['This field is required.']
>>> print(f["message"].errors)
<ul class="errorlist"><li>This field is required.</li></ul>
>>> f["subject"].errors
[]
>>> print(f["subject"].errors)

>>> str(f["subject"].errors)
''

當呈現有錯誤的欄位時,會在欄位的 widget 上設定 aria-invalid="true",以指示螢幕閱讀器使用者有錯誤。

在 Django 5.0 中變更

當欄位有錯誤時,會新增 aria-invalid="true"

BoundField.field

BoundField 包裝的表單 Field 實例。

BoundField.form

BoundField 所綁定的 Form 實例。

BoundField.help_text

欄位的 help_text

BoundField.html_name

將在 widget 的 HTML name 屬性中使用的名稱。它會將 prefix 納入考量。

BoundField.id_for_label[原始碼]

使用此屬性來呈現此欄位的 ID。例如,如果您正在您的範本中手動建構 <label> (儘管 label_tag()/legend_tag() 會為您執行此操作)

<label for="{{ form.my_field.id_for_label }}">...</label>{{ my_field }}

預設情況下,這會是欄位的名稱加上 id_ 前綴(以上範例為「id_my_field」)。您可以透過在欄位的 widget 上設定 attrs 來修改 ID。例如,像這樣宣告一個欄位

my_field = forms.CharField(widget=forms.TextInput(attrs={"id": "myFIELD"}))

並使用上述範本,會呈現類似如下的內容

<label for="myFIELD">...</label><input id="myFIELD" type="text" name="my_field" required>
BoundField.initial[原始碼]

使用 BoundField.initial 來檢索表單欄位的初始資料。它會從 Form.initial 中檢索資料(如果存在),否則會嘗試 Field.initial。可呼叫的值會被評估。請參閱 初始表單值 以取得更多範例。

BoundField.initial 會快取其回傳值,這在處理回傳值可能會變更的可呼叫物件(例如 datetime.nowuuid.uuid4)時特別有用。

>>> from datetime import datetime
>>> class DatedCommentForm(CommentForm):
...     created = forms.DateTimeField(initial=datetime.now)
...
>>> f = DatedCommentForm()
>>> f["created"].initial
datetime.datetime(2021, 7, 27, 9, 5, 54)
>>> f["created"].initial
datetime.datetime(2021, 7, 27, 9, 5, 54)

建議使用 BoundField.initial 而不是 get_initial_for_field()

BoundField.is_hidden[原始碼]

如果此 BoundField 的 widget 是隱藏的,則回傳 True

BoundField.label

欄位的 label。這用於 label_tag()/legend_tag() 中。

BoundField.name

此欄位在表單中的名稱

>>> f = ContactForm()
>>> print(f["subject"].name)
subject
>>> print(f["message"].name)
message
BoundField.template_name[原始碼]
在 Django 5.0 中新增。

使用 BoundField.as_field_group() 呈現的範本名稱。

一個屬性,如果設定了 template_name,則傳回其值,否則傳回 field_template_name

BoundField.use_fieldset[原始碼]

傳回此 BoundField widget 的 use_fieldset 屬性的值。

BoundField.widget_type[原始碼]

傳回包裝欄位 widget 的小寫類別名稱,並移除任何尾隨的 inputwidget。這可用於建構表單,其中版面配置取決於 widget 類型。例如

{% for field in form %}
    {% if field.widget_type == 'checkbox' %}
        # render one way
    {% else %}
        # render another way
    {% endif %}
{% endfor %}

BoundField 的方法

BoundField.as_field_group()
在 Django 5.0 中新增。

使用 BoundField.render() 和預設值來呈現欄位,此方法會使用範本的 template_name(如果已設定)或 field_template_name 來呈現 BoundField,包括其標籤、說明文字和錯誤。

BoundField.as_hidden(attrs=None, **kwargs)[原始碼]

傳回 HTML 字串,將此呈現為 <input type="hidden">

**kwargs 會傳遞至 as_widget()

此方法主要在內部使用。您應該改用 widget。

BoundField.as_widget(widget=None, attrs=None, only_initial=False)[原始碼]

透過呈現傳遞的 widget 來呈現欄位,並新增任何以 attrs 傳遞的 HTML 屬性。如果未指定 widget,則會使用欄位的預設 widget。

only_initial 由 Django 內部使用,不應明確設定。

BoundField.css_classes(extra_classes=None)[原始碼]

當您使用 Django 的呈現捷徑時,CSS 類別會用於指示必要的表單欄位或包含錯誤的欄位。如果您正在手動呈現表單,則可以使用 css_classes 方法來存取這些 CSS 類別。

>>> f = ContactForm(data={"message": ""})
>>> f["message"].css_classes()
'required'

如果您想要在可能需要的錯誤和必要類別之外提供一些額外的類別,您可以將這些類別作為引數提供

>>> f = ContactForm(data={"message": ""})
>>> f["message"].css_classes("foo bar")
'foo bar required'
BoundField.get_context()[原始碼]
在 Django 5.0 中新增。

傳回用於呈現欄位的範本內容。可用的內容為 field,它是已繫結欄位的實例。

BoundField.label_tag(contents=None, attrs=None, label_suffix=None, tag=None)[原始碼]

使用 Form.template_name_label 指定的模板,為表單欄位渲染標籤。

可用的內容如下:

  • field:這是 BoundField 的實例。

  • contents:預設為 BoundField.labelForm.label_suffix (或 Field.label_suffix,如果已設定) 的串連字串。這可以使用 contentslabel_suffix 參數覆寫。

  • attrs:一個包含 forForm.required_css_classiddictid 由欄位的 widget attrsBoundField.auto_id 生成。其他屬性可以使用 attrs 參數提供。

  • use_tag:一個布林值,如果標籤有 id,則為 True。如果為 False,則預設模板會省略 tag

  • tag:一個可選的字串,用於自訂標籤,預設為 label

提示

在您的模板中,fieldBoundField 的實例。因此,field.field 會存取 BoundField.field,這是您宣告的欄位,例如 forms.CharField

若要分別渲染表單欄位的標籤,您可以呼叫其 label_tag() 方法

>>> f = ContactForm(data={"message": ""})
>>> print(f["message"].label_tag())
<label for="id_message">Message:</label>

如果您想自訂渲染,可以覆寫 Form.template_name_label 屬性,或更一般地覆寫預設模板,另請參閱 覆寫內建表單範本

BoundField.legend_tag(contents=None, attrs=None, label_suffix=None)[原始碼]

使用 tag='legend' 呼叫 label_tag(),以使用 <legend> 標籤渲染標籤。當渲染單選和多個核取方塊 widget 時,<legend> 可能比 <label> 更適合,這會很有用。

BoundField.render(template_name=None, context=None, renderer=None)
在 Django 5.0 中新增。

render 方法由 as_field_group 呼叫。所有參數都是可選的,預設值為

透過傳遞 template_name,您可以自訂僅用於單次呼叫的範本。

BoundField.value()[原始碼]

使用這個方法來渲染這個欄位的原始值,就像它會被 Widget 渲染一樣

>>> initial = {"subject": "welcome"}
>>> unbound_form = ContactForm(initial=initial)
>>> bound_form = ContactForm(data={"subject": "hi"}, initial=initial)
>>> print(unbound_form["subject"].value())
welcome
>>> print(bound_form["subject"].value())
hi

自訂 BoundField

如果您需要在模板中存取有關表單欄位的一些其他資訊,並且使用 Field 的子類別不足以滿足您的需求,請考慮自訂 BoundField

自訂表單欄位可以覆寫 get_bound_field()

Field.get_bound_field(form, field_name)[原始碼]

接受 Form 的實例和欄位的名稱。當在模板中存取欄位時,將會使用傳回值。最有可能的情況是,它會是 BoundField 子類別的實例。

例如,如果您有一個 GPSCoordinatesField,並且想要在模板中存取有關座標的其他資訊,可以如下方式實作

class GPSCoordinatesBoundField(BoundField):
    @property
    def country(self):
        """
        Return the country the coordinates lie in or None if it can't be
        determined.
        """
        value = self.value()
        if value:
            return get_country_from_coordinates(value)
        else:
            return None


class GPSCoordinatesField(Field):
    def get_bound_field(self, form, field_name):
        return GPSCoordinatesBoundField(form, self, field_name)

現在您可以使用 {{ form.coordinates.country }} 在模板中存取國家/地區。

將上傳的檔案繫結到表單

處理具有 FileFieldImageField 欄位的表單比一般表單稍微複雜一些。

首先,為了上傳檔案,您需要確保您的 <form> 元素正確地將 enctype 定義為 "multipart/form-data"

<form enctype="multipart/form-data" method="post" action="/foo/">

其次,當您使用表單時,需要繫結檔案資料。檔案資料的處理方式與一般表單資料不同,因此當您的表單包含 FileFieldImageField 時,您需要在繫結表單時指定第二個引數。因此,如果我們擴充 ContactForm 以包含一個名為 mugshotImageField,我們需要繫結包含 mugshot 影像的檔案資料

# Bound form with an image field
>>> from django.core.files.uploadedfile import SimpleUploadedFile
>>> data = {
...     "subject": "hello",
...     "message": "Hi there",
...     "sender": "foo@example.com",
...     "cc_myself": True,
... }
>>> file_data = {"mugshot": SimpleUploadedFile("face.jpg", b"file data")}
>>> f = ContactFormWithMugshot(data, file_data)

實際上,您通常會指定 request.FILES 作為檔案資料的來源 (就像您使用 request.POST 作為表單資料的來源一樣)

# Bound form with an image field, data from the request
>>> f = ContactFormWithMugshot(request.POST, request.FILES)

建構未繫結的表單與以往相同 – 省略表單資料*和*檔案資料

# Unbound form with an image field
>>> f = ContactFormWithMugshot()

測試多部分表單

Form.is_multipart()

如果您正在編寫可重複使用的檢視或範本,您可能無法事先知道您的表單是否為多部分表單。is_multipart() 方法會告訴您表單是否需要多部分編碼以進行提交

>>> f = ContactFormWithMugshot()
>>> f.is_multipart()
True

以下是在範本中如何使用此功能的範例

{% if form.is_multipart %}
    <form enctype="multipart/form-data" method="post" action="/foo/">
{% else %}
    <form method="post" action="/foo/">
{% endif %}
{{ form }}
</form>

子類別化表單

如果您有多個共用欄位的 Form 類別,您可以使用子類別化來消除冗餘。

當您子類別化自訂 Form 類別時,產生的子類別將包含父類別的所有欄位,後接您在子類別中定義的欄位。

在這個範例中,ContactFormWithPriority 包含 ContactForm 的所有欄位,外加一個額外的欄位 priorityContactForm 的欄位會先排序

>>> class ContactFormWithPriority(ContactForm):
...     priority = forms.CharField()
...
>>> f = ContactFormWithPriority(auto_id=False)
>>> print(f)
<div>Subject:<input type="text" name="subject" maxlength="100" required></div>
<div>Message:<textarea name="message" cols="40" rows="10" required></textarea></div>
<div>Sender:<input type="email" name="sender" required></div>
<div>Cc myself:<input type="checkbox" name="cc_myself"></div>
<div>Priority:<input type="text" name="priority" required></div>

可以將多個表單子類化,將表單視為混入(mixins)。在此範例中,BeatleForm 子類化了 PersonFormInstrumentForm(依照此順序),並且其欄位列表包含來自父類別的欄位。

>>> from django import forms
>>> class PersonForm(forms.Form):
...     first_name = forms.CharField()
...     last_name = forms.CharField()
...
>>> class InstrumentForm(forms.Form):
...     instrument = forms.CharField()
...
>>> class BeatleForm(InstrumentForm, PersonForm):
...     haircut_type = forms.CharField()
...
>>> b = BeatleForm(auto_id=False)
>>> print(b)
<div>First name:<input type="text" name="first_name" required></div>
<div>Last name:<input type="text" name="last_name" required></div>
<div>Instrument:<input type="text" name="instrument" required></div>
<div>Haircut type:<input type="text" name="haircut_type" required></div>

可以宣告式地移除從父類別繼承的 Field,方法是在子類別中將該欄位的名稱設定為 None。例如:

>>> from django import forms

>>> class ParentForm(forms.Form):
...     name = forms.CharField()
...     age = forms.IntegerField()
...

>>> class ChildForm(ParentForm):
...     name = None
...

>>> list(ChildForm().fields)
['age']

表單的前綴

Form.prefix

您可以在一個 <form> 標籤內放置多個 Django 表單。若要為每個 Form 提供各自的命名空間,請使用 prefix 關鍵字引數。

>>> mother = PersonForm(prefix="mother")
>>> father = PersonForm(prefix="father")
>>> print(mother)
<div><label for="id_mother-first_name">First name:</label><input type="text" name="mother-first_name" required id="id_mother-first_name"></div>
<div><label for="id_mother-last_name">Last name:</label><input type="text" name="mother-last_name" required id="id_mother-last_name"></div>
>>> print(father)
<div><label for="id_father-first_name">First name:</label><input type="text" name="father-first_name" required id="id_father-first_name"></div>
<div><label for="id_father-last_name">Last name:</label><input type="text" name="father-last_name" required id="id_father-last_name"></div>

前綴也可以在表單類別上指定。

>>> class PersonForm(forms.Form):
...     ...
...     prefix = "person"
...
返回頂部