在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Python/ 使用表單
點(diǎn)擊劫持保護(hù)
安全問(wèn)題歸檔
Model 類(lèi)參考
將遺留數(shù)據(jù)庫(kù)整合到Django
關(guān)聯(lián)對(duì)象參考
內(nèi)建基于類(lèi)的視圖的API
聚合
Django 中的用戶認(rèn)證
django.contrib.humanize
Django管理文檔生成器
分頁(yè)
使用Django輸出CSV
加密簽名
文件儲(chǔ)存API
安全
Django中的測(cè)試
國(guó)際化和本地化
為Django編寫(xiě)首個(gè)補(bǔ)丁
條件表達(dá)式
日志
模型元選項(xiàng)
部署靜態(tài)文件
執(zhí)行查詢
使用Django認(rèn)證系統(tǒng)
基于類(lèi)的視圖
中間件
編寫(xiě)自定義的django-admin命令
Django 的設(shè)置
格式本地化
數(shù)據(jù)庫(kù)訪問(wèn)優(yōu)化
錯(cuò)誤報(bào)告
基于類(lèi)的內(nèi)建通用視圖
編寫(xiě)自定義存儲(chǔ)系統(tǒng)
編寫(xiě)你的第一個(gè) Django 程序 第3部分
編寫(xiě)數(shù)據(jù)庫(kù)遷移
使用表單
編寫(xiě)你的第一個(gè) Django 程序 第2部分
編寫(xiě)你的第一個(gè) Django 程序 第1部分
如何使用會(huì)話
系統(tǒng)檢查框架
新手入門(mén)
信號(hào)
編寫(xiě)視圖
如何使用WSGI 部署
編寫(xiě)你的第一個(gè)Django應(yīng)用,第6部分
常見(jiàn)的網(wǎng)站應(yīng)用工具
Widgets
內(nèi)建的視圖
模型實(shí)例參考
視圖層
Django中的密碼管理
高級(jí)教程:如何編寫(xiě)可重用的應(yīng)用
國(guó)際化和本地化
"本地特色"附加功能
TemplateResponse 和 SimpleTemplateResponse
模式編輯器
文件上傳
快速安裝指南
部署 Django
表單 API
表單素材 ( <code>Media</code> 類(lèi))
管理文件
其它核心功能
查找 API 參考
表單
Admin
數(shù)據(jù)庫(kù)函數(shù)
自定義查找
使用基于類(lèi)的視圖處理表單
管理操作
開(kāi)發(fā)過(guò)程
編寫(xiě)你的第一個(gè)Django應(yīng)用,第5部分
進(jìn)行原始的sql查詢
模型層
多數(shù)據(jù)庫(kù)
編寫(xiě)你的第一個(gè) Django 程序 第4部分
Django安全
Django 初探
Django異常
重定向應(yīng)用
按需內(nèi)容處理
管理器
視圖裝飾器
驗(yàn)證器
使用Django輸出PDF
File對(duì)象
Django 的快捷函數(shù)
基于類(lèi)的通用視圖 —— 索引
為模型提供初始數(shù)據(jù)
模板層
URL調(diào)度器
中間件
模型

使用表單

關(guān)于這頁(yè)文檔

這頁(yè)文檔簡(jiǎn)單介紹Web 表單的基本概念和它們?cè)贒jango 中是如何處理的。關(guān)于表單API 某方面的細(xì)節(jié),請(qǐng)參見(jiàn)表單 API、表單的字段和表單和字段的檢驗(yàn)。

除非你計(jì)劃構(gòu)建的網(wǎng)站和應(yīng)用只是發(fā)布內(nèi)容而不接受訪問(wèn)者的輸入,否則你將需要理解并使用表單。

Django 提供廣泛的工具和庫(kù)來(lái)幫助你構(gòu)建表單來(lái)接收網(wǎng)站訪問(wèn)者的輸入,然后處理以及響應(yīng)輸入。

HTML 表單

在HTML中,表單是位于<form>...</form> 之間的元素的集合,它們?cè)试S訪問(wèn)者輸入文本、選擇選項(xiàng)、操作對(duì)象和控制等等,然后將信息發(fā)送回服務(wù)器。

某些表單的元素 —— 文本輸入和復(fù)選框 —— 非常簡(jiǎn)單而且內(nèi)建于HTML 本身。其它的表單會(huì)復(fù)雜些;例如彈出一個(gè)日期選擇對(duì)話框的界面、允許你移動(dòng)滾動(dòng)條的界面、使用JavaScript 和CSS 以及HTML 表單<input> 元素來(lái)實(shí)現(xiàn)操作控制的界面。

<input> 元素一樣,一個(gè)表單必須指定兩樣?xùn)|西:

  • where:響應(yīng)用戶輸入的URL
  • how:HTTP 方法

例如,Django Admin 站點(diǎn)的登錄表單包含幾個(gè)<input> 元素:type="text" 用于用戶名,type="password" 用于密碼,type="submit" 用于“Log in" 按鈕。它還包含一些用戶看不到的隱藏的文本字段,Django 使用它們來(lái)決定下一步的行為。

它還告訴瀏覽器表單數(shù)據(jù)應(yīng)該發(fā)往<form>action 屬性指定的URL —— /admin/,而且應(yīng)該使用method 屬性指定的HTTP 方法 —— post。

當(dāng)觸發(fā)<input type="submit" value="Log in"> 元素時(shí),數(shù)據(jù)將發(fā)送給/admin/。

GET 和 POST

處理表單時(shí)候只會(huì)用到GETPOST 方法。

Django 的登錄表單使用POST 方法,在這個(gè)方法中瀏覽器組合表單數(shù)據(jù)、對(duì)它們進(jìn)行編碼以用于傳輸、將它們發(fā)送到服務(wù)器然后接收它的響應(yīng)。

相反,GET 組合提交的數(shù)據(jù)為一個(gè)字符串,然后使用它來(lái)生成一個(gè)URL。這個(gè)URL 將包含數(shù)據(jù)發(fā)送的地址以及數(shù)據(jù)的鍵和值。如果你在Django 文檔中做一次搜索,你會(huì)立即看到這點(diǎn),此時(shí)將生成一個(gè)https://docs.djangoproject.com/search/?q=forms&release=1 形式的URL。

GETPOST 用于不同的目的。

用于改變系統(tǒng)狀態(tài)的請(qǐng)求 —— 例如,給數(shù)據(jù)庫(kù)帶來(lái)變化的請(qǐng)求 —— 應(yīng)該使用POST。GET 只應(yīng)該用于不會(huì)影響系統(tǒng)狀態(tài)的請(qǐng)求。

GET 還不適合密碼表單,因?yàn)槊艽a將出現(xiàn)在URL 中,以及瀏覽器的歷史和服務(wù)器的日志中,而且都是以普通的文本格式。它還不適合數(shù)據(jù)量大的表單和二進(jìn)制數(shù)據(jù),例如一張圖片。使用GET 請(qǐng)求作為管理站點(diǎn)的表單具有安全隱患:攻擊者很容易模擬表單請(qǐng)求來(lái)取得系統(tǒng)的敏感數(shù)據(jù)。POST,如果與其它的保護(hù)措施結(jié)合將對(duì)訪問(wèn)提供更多的控制,例如Django 的CSRF 保護(hù)。

另一個(gè)方面,GET 適合網(wǎng)頁(yè)搜索這樣的表單,因?yàn)檫@種表示一個(gè)GET 請(qǐng)求的URL 可以很容易地作為書(shū)簽、分享和重新提交。

Django 在表單中的角色

處理表單是一件很復(fù)雜的事情??紤]一下Django 的Admin 站點(diǎn),不同類(lèi)型的大量數(shù)據(jù)項(xiàng)需要在一個(gè)表單中準(zhǔn)備好、渲染成HTML、使用一個(gè)方便的界面編輯、返回給服務(wù)器、驗(yàn)證并清除,然后保存或者向后繼續(xù)處理。

Django 的表單功能可以簡(jiǎn)化并自動(dòng)化大部分這些工作,而且還可以比大部分程序員自己所編寫(xiě)的代碼更安全。

Django 會(huì)處理表單工作中的三個(gè)顯著不同的部分:

  • 準(zhǔn)備并重新構(gòu)造數(shù)據(jù)
  • 為數(shù)據(jù)創(chuàng)建HTML 表單
  • 接收并處理客戶端提交的表單和數(shù)據(jù)

可以手工編寫(xiě)代碼來(lái)實(shí)現(xiàn),但是Django 可以幫你完成所有這些工作。

Django 中的表單

我們已經(jīng)簡(jiǎn)短講述HTML 表單,但是HTML的<form> 只是其機(jī)制的一部分。

在一個(gè)Web 應(yīng)用中,‘表單’可能指HTML <form>、或者生成它的Django 的Form、或者提交時(shí)發(fā)送的結(jié)構(gòu)化數(shù)據(jù)、或者這些部分的總和。

Django 的Form 類(lèi)

表單系統(tǒng)的核心部分是Django 的Form 類(lèi)。Django 的模型描述一個(gè)對(duì)象的邏輯結(jié)構(gòu)、行為以及展現(xiàn)給我們的方式,與此類(lèi)似,Form 類(lèi)描述一個(gè)表單并決定它如何工作和展現(xiàn)。

模型類(lèi)的字典映射到數(shù)據(jù)庫(kù)的字典,與此類(lèi)似,表單類(lèi)的字段映射到HTML 的表單<input> 元素。(ModelForm通過(guò)一個(gè)Form 映射模型類(lèi)的字段到HTML 表單的<input>元素;Django 的Admin 站點(diǎn)就是基于這個(gè))。

表單的字段本身也是類(lèi);它們管理表單的數(shù)據(jù)并在表單提交時(shí)進(jìn)行驗(yàn)證。DateFieldFileField處理的數(shù)據(jù)類(lèi)型差別很大,必須完成不同的事情。

表單字段在瀏覽器中呈現(xiàn)給用戶的是一個(gè)HTML 的“widget” —— 用戶界面的一個(gè)片段。每個(gè)字段類(lèi)型都有一個(gè)合適的默認(rèn)Widget 類(lèi),需要時(shí)可以覆蓋。

實(shí)例化、處理和渲染表單

在Django 中渲染一個(gè)對(duì)象時(shí),我們通常:

  1. 在視圖中獲得它(例如,從數(shù)據(jù)庫(kù)中獲取)
  2. 將它傳遞給模板上下文
  3. 使用模板變量將它擴(kuò)展為HTML 標(biāo)記

在模板中渲染表單和渲染其它類(lèi)型的對(duì)象幾乎一樣,除了幾個(gè)關(guān)鍵的差別。

在模型實(shí)例不包含數(shù)據(jù)的情況下,在模板中對(duì)它做處理很少有什么用處。但是渲染一個(gè)未填充的表單卻非常有意義 —— 我們希望用戶去填充它。

所以當(dāng)我們?cè)谝晥D中處理模型實(shí)例時(shí),我們一般從數(shù)據(jù)庫(kù)中獲取它。當(dāng)我們處理表單時(shí),我們一般在視圖中實(shí)例化它。

當(dāng)我們實(shí)例化表單時(shí),我們可以選擇讓它為空還是預(yù)先填充它,例如使用:

  • 來(lái)自一個(gè)保存后的模型實(shí)例的數(shù)據(jù)(例如用于編輯的管理表單)
  • 我們從其它地方獲得的數(shù)據(jù)
  • 從前面一個(gè)HTML 表單提交過(guò)來(lái)的數(shù)據(jù)

最后一種情況最令人關(guān)注,因?yàn)樗沟糜脩艨梢圆恢皇情喿x一個(gè)網(wǎng)站,而且可以給網(wǎng)站返回信息。

構(gòu)建一個(gè)表單

需要完成的工作

假設(shè)你想在你的網(wǎng)站上創(chuàng)建一個(gè)簡(jiǎn)單的表單,以獲得用戶的名字。你需要類(lèi)似這樣的模板:

<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>

這告訴瀏覽器發(fā)送表單的數(shù)據(jù)到URL /your-name/,并使用POST 方法。它將顯示一個(gè)標(biāo)簽為"Your name:"的文本字段,和一個(gè)"OK"按鈕。如果模板上下文包含一個(gè)current_name 變量,它將用于預(yù)填充your_name 字段。

你將需要一個(gè)視圖來(lái)渲染這個(gè)包含HTML 表單的模板,并提供合適的current_name 字段。

當(dāng)表單提交時(shí),發(fā)往服務(wù)器的POST 請(qǐng)求將包含表單數(shù)據(jù)。

現(xiàn)在你還需要一個(gè)對(duì)應(yīng)/your-name/ URL 的視圖,它在請(qǐng)求中找到正確的鍵/值對(duì),然后處理它們。

這是一個(gè)非常簡(jiǎn)單的表單。實(shí)際應(yīng)用中,一個(gè)表單可能包含幾十上百個(gè)字段,其中大部分需要預(yù)填充,而且我們預(yù)料到用戶將來(lái)回編輯-提交幾次才能完成操作。

我們可能需要在表單提交之前,在瀏覽器端作一些驗(yàn)證。我們可能想使用非常復(fù)雜的字段,以允許用戶做類(lèi)似從日歷中挑選日期這樣的事情,等等。

這個(gè)時(shí)候,讓Django 來(lái)為我們完成大部分工作是很容易的。

在Django 中構(gòu)建一個(gè)表單

Form 類(lèi)

我們已經(jīng)計(jì)劃好了我們的 HTML 表單應(yīng)該呈現(xiàn)的樣子。在Django 中,我們的起始點(diǎn)是這里:

#forms.py

from django import forms

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

它定義一個(gè)Form 類(lèi),只帶有一個(gè)字段(your_name)。我們已經(jīng)對(duì)這個(gè)字段使用一個(gè)友好的標(biāo)簽,當(dāng)渲染時(shí)它將出現(xiàn)在<label> 中(在這個(gè)例子中,即使我們省略它,我們指定的label還是會(huì)自動(dòng)生成)。

字段允許的最大長(zhǎng)度通過(guò)max_length 定義。它完成兩件事情。首先,它在HTML 的<input> 上放置一個(gè)maxlength="100" (這樣瀏覽器將在第一時(shí)間阻止用戶輸入多于這個(gè)數(shù)目的字符)。它還意味著當(dāng)Django 收到瀏覽器發(fā)送過(guò)來(lái)的表單時(shí),它將驗(yàn)證數(shù)據(jù)的長(zhǎng)度。

Form 的實(shí)例具有一個(gè)is_valid() 方法,它為所有的字段運(yùn)行驗(yàn)證的程序。當(dāng)調(diào)用這個(gè)方法時(shí),如果所有的字段都包含合法的數(shù)據(jù),它將:

  • 返回True
  • 將表單的數(shù)據(jù)放到cleaned_data屬性中。

完整的表單,第一次渲染時(shí),看上去將像:

<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" maxlength="100">

注意它不包含 <form> 標(biāo)簽和提交按鈕。我們必須自己在模板中提供它們。

視圖

發(fā)送給Django 網(wǎng)站的表單數(shù)據(jù)通過(guò)一個(gè)視圖處理,一般和發(fā)布這個(gè)表單的是同一個(gè)視圖。這允許我們重用一些相同的邏輯。

當(dāng)處理表單時(shí),我們需要在視圖中實(shí)例化它:

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

如果訪問(wèn)視圖的是一個(gè)GET 請(qǐng)求,它將創(chuàng)建一個(gè)空的表單實(shí)例并將它放置到要渲染的模板的上下文中。這是我們?cè)诘谝粋€(gè)訪問(wèn)該URL 時(shí)預(yù)期發(fā)生的情況。

如果表單的提交使用POST 請(qǐng)求,那么視圖將再次創(chuàng)建一個(gè)表單實(shí)例并使用請(qǐng)求中的數(shù)據(jù)填充它:form = NameForm(request.POST)。這叫做”綁定數(shù)據(jù)至表單“(它現(xiàn)在是一個(gè)綁定的表單)。

我們調(diào)用表單的is_valid()方法;如果它不為True,我們將帶著這個(gè)表單返回到模板。這時(shí)表單不再為空(未綁定),所以HTML 表單將用之前提交的數(shù)據(jù)填充,然后可以根據(jù)要求編輯并改正它。

如果is_valid()True,我們將能夠在cleaned_data 屬性中找到所有合法的表單數(shù)據(jù)。在發(fā)送HTTP 重定向給瀏覽器告訴它下一步的去向之前,我們可以用這個(gè)數(shù)據(jù)來(lái)更新數(shù)據(jù)庫(kù)或者做其它處理。

模板

我們不需要在name.html 模板中做很多工作。最簡(jiǎn)單的例子是:

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

根據(jù){{ form }},所有的表單字段和它們的屬性將通過(guò)Django 的模板語(yǔ)言拆分成HTML 標(biāo)記 。

表單和跨站請(qǐng)求偽造的防護(hù)

Django 原生支持一個(gè)簡(jiǎn)單易用的跨站請(qǐng)求偽造的防護(hù)。當(dāng)提交一個(gè)啟用CSRF 防護(hù)的POST 表單時(shí),你必須使用上面例子中的csrf_token 模板標(biāo)簽。然而,因?yàn)镃SRF 防護(hù)在模板中不是與表單直接捆綁在一起的,這個(gè)標(biāo)簽在這篇文檔的以下示例中將省略。

HTML5 輸入類(lèi)型和瀏覽器驗(yàn)證

如果你的表單包含URLFieldEmailField 和其它整數(shù)字段類(lèi)似,Django 將使用urlemailnumber 這樣的HTML5 輸入類(lèi)型。默認(rèn)情況下,瀏覽器可能會(huì)對(duì)這些字段進(jìn)行它們自身的驗(yàn)證,這些驗(yàn)證可能比Django 的驗(yàn)證更嚴(yán)格。如果你想禁用這個(gè)行為,請(qǐng)?jiān)O(shè)置form 標(biāo)簽的novalidate 屬性,或者指定一個(gè)不同的字段,如TextInput

現(xiàn)在我們有了一個(gè)可以工作的網(wǎng)頁(yè)表單,它通過(guò)Django Form 描述、通過(guò)視圖處理并渲染成一個(gè)HTML <form>。

這是你入門(mén)所需要知道的所有內(nèi)容,但是表單框架為了提供了更多的內(nèi)容。一旦你理解了上面描述的基本處理過(guò)程,你應(yīng)該可以理解表單系統(tǒng)的其它功能并準(zhǔn)備好學(xué)習(xí)更多的底層機(jī)制。

Django Form 類(lèi)詳解

所有的表單類(lèi)都作為django.forms.Form 的子類(lèi)創(chuàng)建,包括你在Django 管理站點(diǎn)中遇到的ModelForm

模型和表單

實(shí)際上,如果你的表單打算直接用來(lái)添加和編輯Django 的模型,ModelForm 可以節(jié)省你的許多時(shí)間、精力和代碼,因?yàn)樗鼘⒏鶕?jù)Model 類(lèi)構(gòu)建一個(gè)表單以及適當(dāng)?shù)淖侄魏蛯傩浴?/p>

綁定的和未綁定的表單實(shí)例

綁定的和未綁定的表單 之間的區(qū)別非常重要:

  • 未綁定的表單沒(méi)有關(guān)聯(lián)的數(shù)據(jù)。當(dāng)渲染給用戶時(shí),它將為空或包含默認(rèn)的值。
  • 綁定的表單具有提交的數(shù)據(jù),因此可以用來(lái)檢驗(yàn)數(shù)據(jù)是否合法。如果渲染一個(gè)不合法的綁定的表單,它將包含內(nèi)聯(lián)的錯(cuò)誤信息,告訴用戶如何糾正數(shù)據(jù)。

表單的is_bound 屬性將告訴你一個(gè)表單是否具有綁定的數(shù)據(jù)。

字段詳解

考慮一個(gè)比上面的迷你示例更有用的一個(gè)表單,我們可以用它來(lái)在一個(gè)個(gè)人網(wǎng)站上實(shí)現(xiàn)“聯(lián)系我”功能:

#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)

我們前面的表單只使用一個(gè)字段your_name,它是一個(gè)CharField。在這個(gè)例子中,我們的表單具有四個(gè)字段:subject、messagesendercc_myself。共用到三種字段類(lèi)型:CharField、EmailFieldBooleanField;完整的字段類(lèi)型列表可以在表單字段中找到。

Widgets

每個(gè)表單字段都有一個(gè)對(duì)應(yīng)的Widget 類(lèi),它對(duì)應(yīng)一個(gè)HTML 表單Widget,例如<input type="text">。

在大部分情況下,字段都具有一個(gè)合理的默認(rèn)Widget。例如,默認(rèn)情況下,CharField 具有一個(gè)TextInput Widget,它在HTML 中生成一個(gè)<input type="text">。如果你需要<textarea>,在定義表單字段時(shí)你應(yīng)該指定一個(gè)合適的Widget,例如我們定義的message 字段。

字段的數(shù)據(jù)

不管表單提交的是什么數(shù)據(jù),一旦通過(guò)調(diào)用is_valid() 成功驗(yàn)證(is_valid() 返回True),驗(yàn)證后的表單數(shù)據(jù)將位于form.cleaned_data 字典中。這些數(shù)據(jù)已經(jīng)為你轉(zhuǎn)換好為Python 的類(lèi)型。

此時(shí),你依然可以從request.POST 中直接訪問(wèn)到未驗(yàn)證的數(shù)據(jù),但是訪問(wèn)驗(yàn)證后的數(shù)據(jù)更好一些。

在上面的聯(lián)系表單示例中,cc_myself 將是一個(gè)布爾值。類(lèi)似地,IntegerFieldFloatField 字段分別將值轉(zhuǎn)換為Python 的intfloat。

下面是在視圖中如何處理表單數(shù)據(jù):

#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/')

提示

關(guān)于Django 中如何發(fā)送郵件的更多信息,請(qǐng)參見(jiàn)發(fā)送郵件。

有些字段類(lèi)型需要一些額外的處理。例如,使用表單上傳的文件需要不同地處理(它們可以從request.FILES 獲取,而不是request.POST)。如何使用表單處理文件上傳的更多細(xì)節(jié),請(qǐng)參見(jiàn)綁定上傳的文件到一個(gè)表單。

使用表單模板

你需要做的就是將表單實(shí)例放進(jìn)模板的上下文。如果你的表單在Context 中叫做form,那么{{ form }}將正確地渲染它的<label><input>元素。

表單渲染的選項(xiàng)

表單模板的額外標(biāo)簽

不要忘記,表單的輸出不 包含<form>標(biāo)簽,和表單的submit 按鈕。你必須自己提供它們。

對(duì)于<label>/<input> 對(duì),還有幾個(gè)輸出選項(xiàng):

  • {{ form.as_table }} 以表格的形式將它們渲染在<tr> 標(biāo)簽中
  • {{ form.as_p }} 將它們渲染在<p> 標(biāo)簽中
  • {{ form.as_ul }} 將它們渲染在<li> 標(biāo)簽中

注意,你必須自己提供<table><ul> 元素。

下面是我們的ContactForm 實(shí)例的輸出{{ 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>

注意,每個(gè)表單字段具有一個(gè)ID屬性并設(shè)置為id_<field-name>,它被一起的label 標(biāo)簽引用。它對(duì)于確保屏幕閱讀軟件這類(lèi)的輔助計(jì)算非常重要。你還可以自定義label 和 id 生成的方式。

更多信息參見(jiàn) 輸出表單為HTML。

手工渲染字段

我們沒(méi)有必要非要讓Django 來(lái)分拆表單的字段;如果我們喜歡,我們可以手工來(lái)做(例如,這樣允許重新對(duì)字段排序)。每個(gè)字段都是表單的一個(gè)屬性,可以使用{{ form.name_of_field }} 訪問(wèn),并將在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>

渲染表單的錯(cuò)誤信息

當(dāng)然,這個(gè)便利性的代價(jià)是更多的工作。直到現(xiàn)在,我們沒(méi)有擔(dān)心如何展示錯(cuò)誤信息,因?yàn)镈jango 已經(jīng)幫我們處理好。在下面的例子中,我們將自己處理每個(gè)字段的錯(cuò)誤和表單整體的各種錯(cuò)誤。注意,表單和模板頂部的{{ form.non_field_errors }} 查找每個(gè)字段的錯(cuò)誤。

使用{{ form.name_of_field.errors }} 顯示表單錯(cuò)誤的一個(gè)清單,并渲染成一個(gè)ul??瓷先タ赡芟瘢?/p>

<ul class="errorlist">
    <li>Sender is required.</li>
</ul>

這個(gè)ul 有一個(gè)errorlist CSS 類(lèi)型,你可以用它來(lái)定義外觀。如果你希望進(jìn)一步自定義錯(cuò)誤信息的顯示,你可以迭代它們來(lái)實(shí)現(xiàn):

{% if form.subject.errors %}
    <ol>
    {% for error in form.subject.errors %}
        <li><strong>{{ error|escape }}</strong></li>
    {% endfor %}
    </ol>
{% endif %}

空字段錯(cuò)誤(以及使用form.as_p() 時(shí)渲染的隱藏字段錯(cuò)誤)將渲染成一個(gè)額外的CSS 類(lèi)型nonfield 以幫助區(qū)分每個(gè)字段的錯(cuò)誤信息。例如,{{ form.non_field_errors }} 看上去會(huì)像:

<ul class="errorlist nonfield">
    <li>Generic validation error</li>
</ul>
Changed in Django 1.8:

添加上面示例中提到的nonfield CSS 類(lèi)型。

參見(jiàn)Forms API 以獲得關(guān)于錯(cuò)誤、樣式以及在模板中使用表單屬性的更多內(nèi)容。

迭代表單的字段

如果你為你的表單使用相同的HTML,你可以使用{% for %} 循環(huán)迭代每個(gè)字段來(lái)減少重復(fù)的代碼:

{% 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> 標(biāo)簽中的字段Label。它包含表單的label_suffix。例如,默認(rèn)的label_suffix 是一個(gè)冒號(hào):

<label for="id_email">Email address:</label>

{{ field.id_for_label }}

用于這個(gè)字段的ID(在上面的例子中是id_email)。如果你正在手工構(gòu)造label,你可能想使用它代替label_tag。如果你有一些內(nèi)嵌的JavaScript 并且想避免硬編碼字段的ID,這也是有用的。

{{ field.value }}

字段的值,例如someone@example.com。

{{ field.html_name }}

輸入元素的name 屬性中將使用的名稱。它將考慮到表單的前綴。

{{ field.help_text }}

與該字段關(guān)聯(lián)的幫助文檔。

{{ field.errors }}

輸出一個(gè)<ul class="errorlist">,包含這個(gè)字段的驗(yàn)證錯(cuò)誤信息。你可以使用{% for error in field.errors %}自定義錯(cuò)誤的顯示。 這種情況下,循環(huán)中的每個(gè)對(duì)象只是一個(gè)包含錯(cuò)誤信息的簡(jiǎn)單字符串。

{{ field.is_hidden }}

如果字段是隱藏字段,則為True,否則為False。作為模板變量,它不是很有用處,但是可以用于條件測(cè)試,例如:

{% if field.is_hidden %}

{% endif %}

{{ field.field }}

表單類(lèi)中的Field 實(shí)例,通過(guò)BoundField 封裝。你可以使用它來(lái)訪問(wèn)Field 屬性,例如{% char_field.field.max_length %}。

迭代隱藏和可見(jiàn)的字段

如果你正在手工布局模板中的一個(gè)表單,而不是依賴Django 默認(rèn)的表單布局,你可能希望將<input type="hidden"> 字段與非隱藏的字段區(qū)別對(duì)待。例如,因?yàn)殡[藏的字段不會(huì)顯示,在該字段旁邊放置錯(cuò)誤信息可能讓你的用戶感到困惑 —— 所以這些字段的錯(cuò)誤應(yīng)該有區(qū)別地來(lái)處理。

Django 提供兩個(gè)表單方法,它們?cè)试S你獨(dú)立地在隱藏的和可見(jiàn)的字段上迭代:hidden_fields()visible_fields()。下面是使用這兩個(gè)方法對(duì)前面一個(gè)例子的修改:

{% 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 %}

這個(gè)示例沒(méi)有處理隱藏字段中的任何錯(cuò)誤信息。通常,隱藏字段中的錯(cuò)誤意味著表單被篡改,因?yàn)檎5谋韱翁顚?xiě)不會(huì)改變它們。然而,你也可以很容易地為這些表單錯(cuò)誤插入一些錯(cuò)誤信息顯示出來(lái)。

可重用的表單模板

如果你的網(wǎng)站在多個(gè)地方對(duì)表單使用相同的渲染邏輯,你可以保存表單的循環(huán)到一個(gè)單獨(dú)的模板中來(lái)減少重復(fù),然后在其它模板中使用include 標(biāo)簽來(lái)重用它:

# 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 %}

如果傳遞到模板上下文中的表單對(duì)象具有一個(gè)不同的名稱,你可以使用include 標(biāo)簽的with 參數(shù)來(lái)對(duì)它起個(gè)別名:

{% include "form_snippet.html" with form=comment_form %}

如果你發(fā)現(xiàn)自己經(jīng)常這樣做,你可能需要考慮一下創(chuàng)建一個(gè)自定義的inclusion標(biāo)簽。

更深入的主題

這里只是基礎(chǔ),表單還可以完成更多的工作:

另見(jiàn)

表單參考 覆蓋完整的API 參考,包括表單字段、表單Widget 以及表單和字段的驗(yàn)證。

譯者:Django 文檔協(xié)作翻譯小組,原文:Overview。

本文以 CC BY-NC-SA 3.0 協(xié)議發(fā)布,轉(zhuǎn)載請(qǐng)保留作者署名和文章出處。

Django 文檔協(xié)作翻譯小組人手緊缺,有興趣的朋友可以加入我們,完全公益性質(zhì)。交流群:467338606。