{% raw %}
# 使用表單 #
> 關于這頁文檔
>
> 這頁文檔簡單介紹Web 表單的基本概念和它們在Django 中是如何處理的。關于表單API 某方面的細節,請參見[表單 API、表單的字段和表單和字段的檢驗](http://python.usyiyi.cn/django/ref/forms/fields.html)。
除非你計劃構建的網站和應用只是發布內容而不接受訪問者的輸入,否則你將需要理解并使用表單。
Django 提供廣泛的工具和庫來幫助你構建表單來接收網站訪問者的輸入,然后處理以及響應輸入。
## HTML 表單 ##
在HTML中,表單是位于`<form>...</form>` 之間的元素的集合,它們允許訪問者輸入文本、選擇選項、操作對象和控制等等,然后將信息發送回服務器。
某些表單的元素 —— 文本輸入和復選框 —— 非常簡單而且內建于HTML 本身。其它的表單會復雜些;例如彈出一個日期選擇對話框的界面、允許你移動滾動條的界面、使用JavaScript 和CSS 以及HTML 表單`<input>` 元素來實現操作控制的界面。
與`<input>` 元素一樣,一個表單必須指定兩樣東西:
+ where:響應用戶輸入的URL
+ how:HTTP 方法
例如,Django Admin 站點的登錄表單包含幾個`<input>` 元素:`type="text"` 用于用戶名,`type="password"` 用于密碼,`type="submit"` 用于“Log in" 按鈕。它還包含一些用戶看不到的隱藏的文本字段,Django 使用它們來決定下一步的行為。
它還告訴瀏覽器表單數據應該發往`<form>` 的`action` 屬性指定的URL —— `/admin/`,而且應該使用`method` 屬性指定的HTTP 方法 —— `post`。
當觸發`<input type="submit" value="Log in">` 元素時,數據將發送給`/admin/`。
### GET 和 POST ###
處理表單時候只會用到`GET `和` POST` 方法。
Django 的登錄表單使用POST 方法,在這個方法中瀏覽器組合表單數據、對它們進行編碼以用于傳輸、將它們發送到服務器然后接收它的響應。
相反,GET 組合提交的數據為一個字符串,然后使用它來生成一個URL。這個URL 將包含數據發送的地址以及數據的鍵和值。如果你在Django 文檔中做一次搜索,你會立即看到這點,此時將生成一個`https://docs.djangoproject.com/search/?q=forms&release=1` 形式的URL。
`GET` 和`POST` 用于不同的目的。
用于改變系統狀態的請求 —— 例如,給數據庫帶來變化的請求 —— 應該使用`POST`。`GET` 只應該用于不會影響系統狀態的請求。
`GET` 還不適合密碼表單,因為密碼將出現在URL 中,以及瀏覽器的歷史和服務器的日志中,而且都是以普通的文本格式。它還不適合數據量大的表單和二進制數據,例如一張圖片。使用GET 請求作為管理站點的表單具有安全隱患:攻擊者很容易模擬表單請求來取得系統的敏感數據。`POST`,如果與其它的保護措施結合將對訪問提供更多的控制,例如Django 的[CSRF 保護](http://python.usyiyi.cn/django/ref/csrf.html)。
另一個方面,`GET` 適合網頁搜索這樣的表單,因為這種表示一個`GET` 請求的URL 可以很容易地作為書簽、分享和重新提交。
Django 在表單中的角色
處理表單是一件很復雜的事情。考慮一下Django 的Admin 站點,不同類型的大量數據項需要在一個表單中準備好、渲染成HTML、使用一個方便的界面編輯、返回給服務器、驗證并清除,然后保存或者向后繼續處理。
Django 的表單功能可以簡化并自動化大部分這些工作,而且還可以比大部分程序員自己所編寫的代碼更安全。
Django 會處理表單工作中的三個顯著不同的部分:
+ 準備并重新構造數據
+ 為數據創建HTML 表單
+ 接收并處理客戶端提交的表單和數據
可以手工編寫代碼來實現,但是Django 可以幫你完成所有這些工作。
## Django 中的表單 ##
我們已經簡短講述HTML 表單,但是HTML的`<form>` 只是其機制的一部分。
在一個Web 應用中,‘表單’可能指HTML `<form>`、或者生成它的Django 的`Form`、或者提交時發送的結構化數據、或者這些部分的總和。
### Django 的Form 類 ###
表單系統的核心部分是Django 的`Form` 類。Django 的模型描述一個對象的邏輯結構、行為以及展現給我們的方式,與此類似,`Form` 類描述一個表單并決定它如何工作和展現。
模型類的字典映射到數據庫的字典,與此類似,表單類的字段映射到HTML 的表單`<input>` 元素。(`ModelForm `通過一個`Form` 映射模型類的字段到HTML 表單的`<input> `元素;Django 的Admin 站點就是基于這個)。
表單的字段本身也是類;它們管理表單的數據并在表單提交時進行驗證。`DateField` 和`FileField `處理的數據類型差別很大,必須完成不同的事情。
表單字段在瀏覽器中呈現給用戶的是一個HTML 的“widget” —— 用戶界面的一個片段。每個字段類型都有一個合適的默認[Widget 類](http://python.usyiyi.cn/django/ref/forms/widgets.html),需要時可以覆蓋。
### 實例化、處理和渲染表單 ###
在Django 中渲染一個對象時,我們通常:
1. 在視圖中獲得它(例如,從數據庫中獲取)
2. 將它傳遞給模板上下文
3. 使用模板變量將它擴展為HTML 標記
在模板中渲染表單和渲染其它類型的對象幾乎一樣,除了幾個關鍵的差別。
在模型實例不包含數據的情況下,在模板中對它做處理很少有什么用處。但是渲染一個未填充的表單卻非常有意義 —— 我們希望用戶去填充它。
所以當我們在視圖中處理模型實例時,我們一般從數據庫中獲取它。當我們處理表單時,我們一般在視圖中實例化它。
當我們實例化表單時,我們可以選擇讓它為空還是預先填充它,例如使用:
+ 來自一個保存后的模型實例的數據(例如用于編輯的管理表單)
+ 我們從其它地方獲得的數據
+ 從前面一個HTML 表單提交過來的數據
最后一種情況最令人關注,因為它使得用戶可以不只是閱讀一個網站,而且可以給網站返回信息。
## 構建一個表單 ##
### 需要完成的工作 ###
假設你想在你的網站上創建一個簡單的表單,以獲得用戶的名字。你需要類似這樣的模板:
```
<form action="/your-name/" method="post">
<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" value="{{ current_name }}">
<input type="submit" value="OK">
</form>
```
這告訴瀏覽器發送表單的數據到URL `/your-name/`,并使用`POST` 方法。它將顯示一個標簽為"Your name:"的文本字段,和一個"OK"按鈕。如果模板上下文包含一個`current_name` 變量,它將用于預填充`your_name` 字段。
你將需要一個視圖來渲染這個包含HTML 表單的模板,并提供合適的`current_name` 字段。
當表單提交時,發往服務器的`POST` 請求將包含表單數據。
現在你還需要一個對應`/your-name/` URL 的視圖,它在請求中找到正確的鍵/值對,然后處理它們。
這是一個非常簡單的表單。實際應用中,一個表單可能包含幾十上百個字段,其中大部分需要預填充,而且我們預料到用戶將來回編輯-提交幾次才能完成操作。
我們可能需要在表單提交之前,在瀏覽器端作一些驗證。我們可能想使用非常復雜的字段,以允許用戶做類似從日歷中挑選日期這樣的事情,等等。
這個時候,讓Django 來為我們完成大部分工作是很容易的。
### 在Django 中構建一個表單 ###
#### Form 類 ####
我們已經計劃好了我們的 HTML 表單應該呈現的樣子。在Django 中,我們的起始點是這里:
```
#forms.py
from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(label='Your name', max_length=100)
```
它定義一個`Form` 類,只帶有一個字段(`your_name`)。我們已經對這個字段使用一個友好的標簽,當渲染時它將出現在`<label>` 中(在這個例子中,即使我們省略它,我們指定的`label`還是會自動生成)。
字段允許的最大長度通過`max_length` 定義。它完成兩件事情。首先,它在HTML 的`<input>` 上放置一個`maxlength="100"` (這樣瀏覽器將在第一時間阻止用戶輸入多于這個數目的字符)。它還意味著當Django 收到瀏覽器發送過來的表單時,它將驗證數據的長度。
`Form` 的實例具有一個`is_valid()` 方法,它為所有的字段運行驗證的程序。當調用這個方法時,如果所有的字段都包含合法的數據,它將:
+ 返回`True`
+ 將表單的數據放到`cleaned_data `屬性中。
完整的表單,第一次渲染時,看上去將像:
```
<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" maxlength="100">
```
注意它不包含 `<form>` 標簽和提交按鈕。我們必須自己在模板中提供它們。
#### 視圖 ####
發送給Django 網站的表單數據通過一個視圖處理,一般和發布這個表單的是同一個視圖。這允許我們重用一些相同的邏輯。
當處理表單時,我們需要在視圖中實例化它:
```
#views.py
from django.shortcuts import render
from django.http import HttpResponseRedirect
from .forms import NameForm
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'name.html', {'form': form})
```
如果訪問視圖的是一個`GET` 請求,它將創建一個空的表單實例并將它放置到要渲染的模板的上下文中。這是我們在第一個訪問該URL 時預期發生的情況。
如果表單的提交使用`POST` 請求,那么視圖將再次創建一個表單實例并使用請求中的數據填充它:`form = NameForm(request.POST)`。這叫做”綁定數據至表單“(它現在是一個綁定的表單)。
我們調用表單的`is_valid() `方法;如果它不為`True`,我們將帶著這個表單返回到模板。這時表單不再為空(未綁定),所以HTML 表單將用之前提交的數據填充,然后可以根據要求編輯并改正它。
如果`is_valid() `為`True`,我們將能夠在`cleaned_data` 屬性中找到所有合法的表單數據。在發送HTTP 重定向給瀏覽器告訴它下一步的去向之前,我們可以用這個數據來更新數據庫或者做其它處理。
#### 模板 ####
我們不需要在name.html 模板中做很多工作。最簡單的例子是:
```
<form action="/your-name/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
```
根據`{{ form }}`,所有的表單字段和它們的屬性將通過Django 的模板語言拆分成HTML 標記 。
> 表單和跨站請求偽造的防護
>
> Django 原生支持一個簡單易用的[跨站請求偽造的防護](http://python.usyiyi.cn/django/ref/csrf.html)。當提交一個啟用CSRF 防護的`POST` 表單時,你必須使用上面例子中的`csrf_token` 模板標簽。然而,因為CSRF 防護在模板中不是與表單直接捆綁在一起的,這個標簽在這篇文檔的以下示例中將省略。
> HTML5 輸入類型和瀏覽器驗證
>
> 如果你的表單包含`URLField`、`EmailField` 和其它整數字段類似,Django 將使用`url`、`email`和 `number` 這樣的HTML5 輸入類型。默認情況下,瀏覽器可能會對這些字段進行它們自身的驗證,這些驗證可能比Django 的驗證更嚴格。如果你想禁用這個行為,請設置`form` 標簽的`novalidate` 屬性,或者指定一個不同的字段,如`TextInput`。
現在我們有了一個可以工作的網頁表單,它通過Django Form 描述、通過視圖處理并渲染成一個HTML `<form>`。
這是你入門所需要知道的所有內容,但是表單框架為了提供了更多的內容。一旦你理解了上面描述的基本處理過程,你應該可以理解表單系統的其它功能并準備好學習更多的底層機制。
## Django Form 類詳解 ##
所有的表單類都作為`django.forms.Form` 的子類創建,包括你在Django 管理站點中遇到的`ModelForm`。
> 模型和表單
>
> 實際上,如果你的表單打算直接用來添加和編輯Django 的模型,[ModelForm](http://python.usyiyi.cn/django/topics/forms/modelforms.html) 可以節省你的許多時間、精力和代碼,因為它將根據`Model` 類構建一個表單以及適當的字段和屬性。
### 綁定的和未綁定的表單實例 ###
綁定的和未綁定的表單 之間的區別非常重要:
+ 未綁定的表單沒有關聯的數據。當渲染給用戶時,它將為空或包含默認的值。
+ 綁定的表單具有提交的數據,因此可以用來檢驗數據是否合法。如果渲染一個不合法的綁定的表單,它將包含內聯的錯誤信息,告訴用戶如何糾正數據。
表單的`is_bound` 屬性將告訴你一個表單是否具有綁定的數據。
### 字段詳解 ###
考慮一個比上面的迷你示例更有用的一個表單,我們可以用它來在一個個人網站上實現“聯系我”功能:
```
#forms.py
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField(widget=forms.Textarea)
sender = forms.EmailField()
cc_myself = forms.BooleanField(required=False)
```
我們前面的表單只使用一個字段`your_name`,它是一個`CharField`。在這個例子中,我們的表單具有四個字段:`subject`、`message`、`sender` 和`cc_myself`。共用到三種字段類型:`CharField`、`EmailField` 和 `BooleanField`;完整的字段類型列表可以在表單字段中找到。
#### Widgets ####
每個表單字段都有一個對應的`Widget` 類,它對應一個HTML 表單`Widget`,例如`<input type="text">`。
在大部分情況下,字段都具有一個合理的默認Widget。例如,默認情況下,`CharField` 具有一個`TextInput Widget`,它在HTML 中生成一個`<input type="text">`。如果你需要`<textarea>`,在定義表單字段時你應該指定一個合適的`Widget`,例如我們定義的`message` 字段。
#### 字段的數據 ####
不管表單提交的是什么數據,一旦通過調用`is_valid()` 成功驗證(`is_valid()` 返回`True`),驗證后的表單數據將位于`form.cleaned_data` 字典中。這些數據已經為你轉換好為Python 的類型。
> 注
>
> 此時,你依然可以從`request.POST` 中直接訪問到未驗證的數據,但是訪問驗證后的數據更好一些。
在上面的聯系表單示例中,`cc_myself` 將是一個布爾值。類似地,`IntegerField` 和`FloatField` 字段分別將值轉換為Python 的`int` 和`float`。
下面是在視圖中如何處理表單數據:
```
#views.py
from django.core.mail import send_mail
if form.is_valid():
subject = form.cleaned_data['subject']
message = form.cleaned_data['message']
sender = form.cleaned_data['sender']
cc_myself = form.cleaned_data['cc_myself']
recipients = ['info@example.com']
if cc_myself:
recipients.append(sender)
send_mail(subject, message, sender, recipients)
return HttpResponseRedirect('/thanks/')
```
> 提示
>
> 關于Django 中如何發送郵件的更多信息,請參見發送郵件。
有些字段類型需要一些額外的處理。例如,使用表單上傳的文件需要不同地處理(它們可以從`request.FILES` 獲取,而不是`request.POST`)。如何使用表單處理文件上傳的更多細節,請參見[綁定上傳的文件到一個表單](http://python.usyiyi.cn/django/ref/forms/api.html#binding-uploaded-files)。
## 使用表單模板 ##
你需要做的就是將表單實例放進模板的上下文。如果你的表單在`Contex`t 中叫做`form`,那么` {{ form }} `將正確地渲染它的`<label>` 和 `<input>`元素。
### 表單渲染的選項 ###
> 表單模板的額外標簽
>
> 不要忘記,表單的輸出不 包含`<form> `標簽,和表單的`submit` 按鈕。你必須自己提供它們。
對于`<label>/<input>` 對,還有幾個輸出選項:
+ `{{ form.as_table }}` 以表格的形式將它們渲染在`<tr>` 標簽中
+ `{{ form.as_p }} ` 將它們渲染在`<p>` 標簽中
+ `{{ form.as_ul }}` 將它們渲染在`<li>` 標簽中
注意,你必須自己提供`<table>` 或`<ul>` 元素。
下面是我們的`ContactForm` 實例的輸出`{{ form.as_p }}`:
```
<p><label for="id_subject">Subject:</label>
<input id="id_subject" type="text" name="subject" maxlength="100" /></p>
<p><label for="id_message">Message:</label>
<input type="text" name="message" id="id_message" /></p>
<p><label for="id_sender">Sender:</label>
<input type="email" name="sender" id="id_sender" /></p>
<p><label for="id_cc_myself">Cc myself:</label>
<input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>
```
注意,每個表單字段具有一個`ID `屬性并設置為`id_<field-name>`,它被一起的`label` 標簽引用。它對于確保屏幕閱讀軟件這類的輔助計算非常重要。你還可以[自定義label 和 id 生成的方式](http://python.usyiyi.cn/django/ref/forms/api.html#ref-forms-api-configuring-label)。
更多信息參見 [輸出表單為HTML](http://python.usyiyi.cn/django/ref/forms/api.html#ref-forms-api-outputting-html)。
### 手工渲染字段 ###
我們沒有必要非要讓Django 來分拆表單的字段;如果我們喜歡,我們可以手工來做(例如,這樣允許重新對字段排序)。每個字段都是表單的一個屬性,可以使用`{{ form.name_of_field }}` 訪問,并將在Django 模板中正確地渲染。例如:
```
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="{{ form.subject.id_for_label }}">Email subject:</label>
{{ form.subject }}
</div>
<div class="fieldWrapper">
{{ form.message.errors }}
<label for="{{ form.message.id_for_label }}">Your message:</label>
{{ form.message }}
</div>
<div class="fieldWrapper">
{{ form.sender.errors }}
<label for="{{ form.sender.id_for_label }}">Your email address:</label>
{{ form.sender }}
</div>
<div class="fieldWrapper">
{{ form.cc_myself.errors }}
<label for="{{ form.cc_myself.id_for_label }}">CC yourself?</label>
{{ form.cc_myself }}
</div>
```
完整的`<label>` 元素還可以使用`label_tag()` 生成。例如:
```
<div class="fieldWrapper">
{{ form.subject.errors }}
{{ form.subject.label_tag }}
{{ form.subject }}
</div>
```
#### 渲染表單的錯誤信息 ####
當然,這個便利性的代價是更多的工作。直到現在,我們沒有擔心如何展示錯誤信息,因為Django 已經幫我們處理好。在下面的例子中,我們將自己處理每個字段的錯誤和表單整體的各種錯誤。注意,表單和模板頂部的`{{ form.non_field_errors }}` 查找每個字段的錯誤。
使用`{{ form.name_of_field.errors }}` 顯示表單錯誤的一個清單,并渲染成一個`ul`。看上去可能像:
```
<ul class="errorlist">
<li>Sender is required.</li>
</ul>
```
這個`ul` 有一個`errorlist` CSS 類型,你可以用它來定義外觀。如果你希望進一步自定義錯誤信息的顯示,你可以迭代它們來實現:
```
{% if form.subject.errors %}
<ol>
{% for error in form.subject.errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ol>
{% endif %}
```
空字段錯誤(以及使用`form.as_p()` 時渲染的隱藏字段錯誤)將渲染成一個額外的CSS 類型`nonfield` 以幫助區分每個字段的錯誤信息。例如,`{{ form.non_field_errors }}` 看上去會像:
```
<ul class="errorlist nonfield">
<li>Generic validation error</li>
</ul>
```
```
Changed in Django 1.8:
添加上面示例中提到的nonfield CSS 類型。
```
參見[Forms API](http://python.usyiyi.cn/django/ref/forms/api.html) 以獲得關于錯誤、樣式以及在模板中使用表單屬性的更多內容。
### 迭代表單的字段 ###
如果你為你的表單使用相同的HTML,你可以使用`{% for %}` 循環迭代每個字段來減少重復的代碼:
```
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
```
`{{ field }}` 中有用的屬性包括:
`{{ field.label }}`
字段的`label`,例如`Email address`。
`{{ field.label_tag }}`
包含在HTML `<label>` 標簽中的字段`Label`。它包含表單的`label_suffix`。例如,默認的`label_suffix` 是一個冒號:
```
<label for="id_email">Email address:</label>
```
`{{ field.id_for_label }}`
用于這個字段的`ID`(在上面的例子中是`id_email`)。如果你正在手工構造`label`,你可能想使用它代替`label_tag`。如果你有一些內嵌的JavaScript 并且想避免硬編碼字段的`ID`,這也是有用的。
`{{ field.value }}`
字段的值,例如`someone@example.com`。
`{{ field.html_name }}`
輸入元素的`name` 屬性中將使用的名稱。它將考慮到表單的前綴。
`{{ field.help_text }}`
與該字段關聯的幫助文檔。
`{{ field.errors }}`
輸出一個`<ul class="errorlist">`,包含這個字段的驗證錯誤信息。你可以使用`{% for error in field.errors %}`自定義錯誤的顯示。 這種情況下,循環中的每個對象只是一個包含錯誤信息的簡單字符串。
`{{ field.is_hidden }}`
如果字段是隱藏字段,則為`True`,否則為`False`。作為模板變量,它不是很有用處,但是可以用于條件測試,例如:
```
{% if field.is_hidden %}
{% endif %}
```
`{{ field.field }}`
表單類中的`Field` 實例,通過`BoundField` 封裝。你可以使用它來訪問`Field` 屬性,例如`{% char_field.field.max_length %}。`
#### 迭代隱藏和可見的字段 ####
如果你正在手工布局模板中的一個表單,而不是依賴Django 默認的表單布局,你可能希望將`<input type="hidden">` 字段與非隱藏的字段區別對待。例如,因為隱藏的字段不會顯示,在該字段旁邊放置錯誤信息可能讓你的用戶感到困惑 —— 所以這些字段的錯誤應該有區別地來處理。
Django 提供兩個表單方法,它們允許你獨立地在隱藏的和可見的字段上迭代:`hidden_fields()` 和`visible_fields()`。下面是使用這兩個方法對前面一個例子的修改:
```
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
```
這個示例沒有處理隱藏字段中的任何錯誤信息。通常,隱藏字段中的錯誤意味著表單被篡改,因為正常的表單填寫不會改變它們。然而,你也可以很容易地為這些表單錯誤插入一些錯誤信息顯示出來。
### 可重用的表單模板 ###
如果你的網站在多個地方對表單使用相同的渲染邏輯,你可以保存表單的循環到一個單獨的模板中來減少重復,然后在其它模板中使用`include` 標簽來重用它:
```
# In your form template:
{% include "form_snippet.html" %}
# In form_snippet.html:
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
```
如果傳遞到模板上下文中的表單對象具有一個不同的名稱,你可以使用`include` 標簽的`with` 參數來對它起個別名:
```
{% include "form_snippet.html" with form=comment_form %}
```
如果你發現自己經常這樣做,你可能需要考慮一下創建一個自定義的` inclusion `標簽。
## 更深入的主題 ##
這里只是基礎,表單還可以完成更多的工作:
+ [表單集](http://python.usyiyi.cn/django/topics/forms/formsets.html)
+ [在表單集中使用初始化數據](http://python.usyiyi.cn/django/topics/forms/formsets.html#using-initial-data-with-a-formset)
+ [限制表單的最大數目](http://python.usyiyi.cn/django/topics/forms/formsets.html#limiting-the-maximum-number-of-forms)
+ [表單集的驗證](http://python.usyiyi.cn/django/topics/forms/formsets.html#formset-validation)
+ [驗證表單集中表單的數目](http://python.usyiyi.cn/django/topics/forms/formsets.html#validating-the-number-of-forms-in-a-formset)
+ [處理表單的排序和刪除](http://python.usyiyi.cn/django/topics/forms/formsets.html#dealing-with-ordering-and-deletion-of-forms)
+ [添加額外的字段到表單中](http://python.usyiyi.cn/django/topics/forms/formsets.html#adding-additional-fields-to-a-formset)
+ [在視圖和模板中視圖表單集](http://python.usyiyi.cn/django/topics/forms/formsets.html#using-a-formset-in-views-and-templates)
+ [從模型中創建表單](http://python.usyiyi.cn/django/topics/forms/modelforms.html)
+ [ModelForm](http://python.usyiyi.cn/django/topics/forms/modelforms.html#modelform)
+ [模型表單集](http://python.usyiyi.cn/django/topics/forms/modelforms.html#model-formsets)
+ [Inline formsets](http://python.usyiyi.cn/django/topics/forms/modelforms.html#inline-formsets)
+ [表單集(`Media` 類)](http://python.usyiyi.cn/django/topics/forms/media.html)
+ [Assets as a static definition](http://python.usyiyi.cn/django/topics/forms/media.html#assets-as-a-static-definition)
+ [`Media` as a dynamic property](http://python.usyiyi.cn/django/topics/forms/media.html#media-as-a-dynamic-property)
+ [Paths in asset definitions](http://python.usyiyi.cn/django/topics/forms/media.html#paths-in-asset-definitions)
+ [`Media` 對象](http://python.usyiyi.cn/django/topics/forms/media.html#media-objects)
+ [表單中的`Media`](http://python.usyiyi.cn/django/topics/forms/media.html#media-on-forms)
> 另見
>
> [表單參考](http://python.usyiyi.cn/django/ref/forms/index.html)
> 覆蓋完整的API 參考,包括表單字段、表單Widget 以及表單和字段的驗證。
‍
> 譯者:[Django 文檔協作翻譯小組](http://python.usyiyi.cn/django/index.html),原文:[Overview](https://docs.djangoproject.com/en/1.8/topics/forms/)。
>
> 本文以 [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/cn/) 協議發布,轉載請保留作者署名和文章出處。
>
> [Django 文檔協作翻譯小組](http://python.usyiyi.cn/django/index.html)人手緊缺,有興趣的朋友可以加入我們,完全公益性質。交流群:467338606。
{% endraw %}
- 新手入門
- 從零開始
- 概覽
- 安裝
- 教程
- 第1部分:模型
- 第2部分:管理站點
- 第3部分:視圖和模板
- 第4部分:表單和通用視圖
- 第5部分:測試
- 第6部分:靜態文件
- 高級教程
- 如何編寫可重用的應用
- 為Django編寫首個補丁
- 模型層
- 模型
- 模型語法
- 元選項
- 模型類
- 查詢集
- 執行查詢
- 查找表達式
- 模型的實例
- 實例方法
- 訪問關聯對象
- 遷移
- 模式編輯器
- 編寫遷移
- 高級
- 管理器
- 原始的SQL查詢
- 聚合
- 多數據庫
- 自定義查找
- 條件表達式
- 數據庫函數
- 其它
- 遺留的數據庫
- 提供初始數據
- 優化數據庫訪問
- 視圖層
- 基礎
- URL配置
- 視圖函數
- 快捷函數
- 裝飾器
- 參考
- 內建的視圖
- TemplateResponse 對象
- 文件上傳
- 概覽
- File 對象
- 儲存API
- 管理文件
- 自定義存儲
- 基于類的視圖
- 概覽
- 內建顯示視圖
- 內建編輯視圖
- API參考
- 分類索引
- 高級
- 生成 CSV
- 生成 PDF
- 中間件
- 概覽
- 內建的中間件類
- 模板層
- 基礎
- 面向設計師
- 語言概覽
- 人性化
- 面向程序員
- 表單
- 基礎
- 概覽
- 表單API
- 內建的Widget
- 高級
- 整合媒體
- 開發過程
- 設置
- 概覽
- 應用程序
- 異常
- 概覽
- django-admin 和 manage.py
- 添加自定義的命令
- 測試
- 介紹
- 部署
- 概述
- WSGI服務器
- 部署靜態文件
- 通過email追蹤代碼錯誤
- Admin
- 管理操作
- 管理文檔生成器
- 安全
- 安全概述
- 說明Django中的安全問題
- 點擊劫持保護
- 加密簽名
- 國際化和本地化
- 概述
- 本地化WEB UI格式化輸入
- “本地特色”
- 常見的網站應用工具
- 認證
- 概覽
- 使用認證系統
- 密碼管理
- 日志
- 分頁
- 會話
- 數據驗證
- 其它核心功能
- 按需內容處理
- 重定向
- 信號
- 系統檢查框架