Django教程--Form表單
前面我們已經(jīng)了解如何在django中使用GET凌停、POST傳遞數(shù)據(jù),但是我們并沒有對用戶提交的數(shù)據(jù)進(jìn)行驗證(為何需要驗證大家都懂得)隅俘,對于驗證我們可以自己寫相關(guān)代碼進(jìn)行判斷(最基本也有效的方法),但是django作為一個集大成的全面框架,為我們提供了一種更優(yōu)雅簡單的方式断盛,那就是今天的主角--Form,F(xiàn)orm不僅僅具有數(shù)據(jù)驗證功能愉舔,還可以生成用于提交的html標(biāo)簽钢猛,接下來我們就來了解一下如何使用Form。
Form基本使用
按照慣例轩缤,我們先來段代碼演示如何使用命迈,接著前面的PostParams工程,我們在app目錄下新建forms.py文件火的,用來存放Form表單的代碼壶愤,代碼如下:
from django import forms
class RegisterForm(forms.Form):
username=forms.CharField(label='username',max_length=20,required=True,error_messages={'required':'username cannot be null'})
password=forms.CharField(label='password',widget=forms.PasswordInput,required=True,error_messages={'required':'password cannot be null'})
email=forms.EmailField(label='email',required=True,
error_messages={'required': u'email cannot be null','invalid': u'email format is wrong'},
widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'email'}))
image=forms.ImageField(label='headimage',required=False)
從代碼可以看到,使用Form我們需要定義一個類繼承自forms.Form,然后定義幾個變量(forms以經(jīng)為什么提供了多種輸入框馏鹤,甚至Email都有征椒,對于Email會自己做個正則表達(dá)判斷),需要注意變量名對應(yīng)html表單的name屬性湃累,每個屬性有不同的校驗規(guī)則(下面會仔細(xì)介紹勃救,暫時先具體看下用法),我們還可以自定義每個屬性的widget和label(用于生成html標(biāo)簽)以及校驗錯誤返回的信息治力。
接下來我們在views.py里新建一個視圖函數(shù)代碼如下:
def form_view(request):
if request.method=='GET':
register_form=RegisterForm()
return render(request,'form.html',{'form':register_form})
else:
register_form=RegisterForm(request.POST or None,request.FILES or None)
if register_form.is_valid():
return HttpResponse('username:'+register_form.cleaned_data['username']+'&password:'+register_form.cleaned_data['password']+'&email:'+register_form.cleaned_data['email'])
else:
return render(request, 'form.html', {'form': register_form})
當(dāng)然我們也要建立對應(yīng)的模板文件form.html代碼如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post" enctype="multipart/form-data" >
{%csrf_token%}
<p>{{form.username.label}}:{{form.username}}</p>
{%if form.errors.username%}
{{form.errors.username}}
{%endif%}
<p>{{form.password.label}}:{{form.password}}</p>
{%if form.errors.password%}
{{form.errors.password}}
{%endif%}
<p>{{form.email.label}}:{{form.email}}</p>
{%if form.errors.email%}
{{form.errors.email}}
{%endif%}
<P>{{form.image.label}}:{{form.image}}</P>
{%if form.errors.image%}
{{form.errors.image}}
{%endif%}
<input type="submit" value="Submit">
</form>
</body>
</html>
然后在urls.py中添加攔截
from django.conf.urls import patterns, include, url
from django.contrib import admin
from app.views import params_test, params_test_reg, params_post, form_view
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'PostParams.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^params_test/$',params_test),
url(r'^params_test_reg/str(?P<str>\w+)page(?P<page>\d+)/$',params_test_reg),
url(r'^post/$',params_post),
url(r'^form/$',form_view),
)
啟動服務(wù)器蒙秒,輸入http://127.0.0.1:8000/form/即可看到對應(yīng)的表單,輸入相關(guān)信息然后提交琴许,如果滿足驗證要求税肪,就會返回輸入信息,當(dāng)不滿足的時候就會重新跳回表單界面并提示錯誤信息榜田。
Form表單代碼解析
上面我們已經(jīng)展示了如何使用Form表單益兄,接下來我們就來分析下上述代碼并講解Form。
先看Forms.py代碼箭券,F(xiàn)orm為我們提供了格式各樣的Field净捅,用于應(yīng)對各種各樣的輸入場景,例如本代碼里面首先定義了四個需要提交的屬性辩块,每個屬性各不相同蛔六,例如username需要文本輸入框使用CharField,password同樣需要文本輸入框但是需要密碼輸入框荆永,所以需要設(shè)置widget為密碼輸入框,對于email需要對輸入的格式進(jìn)行驗證是否為正確的郵箱国章,所以需要EmailField,而對于圖像文件則有對應(yīng)的ImageField具钥,對于這些屬性我們還可以通過required指定哪些是必須輸入(默認(rèn)為True),我們還可以通過指定error_messages驗證錯誤時顯示的信息液兽。
定義好表單后我們需要在視圖函數(shù)中使用該表單骂删,例如本例中先判斷是否為get請求,如果為get請求就創(chuàng)建表單然后傳給模板四啰,在模板中我們只需使用{{}}標(biāo)簽輸出表單對應(yīng)的屬性宁玫,然后就會自動渲染出該屬性對應(yīng)的widget的代碼,我們可以更改widget甚至自定義widget來達(dá)到自己的個性化網(wǎng)頁輸入需求柑晒,當(dāng)然我們還要判斷當(dāng)前表單是否有驗證錯誤欧瘪,如果發(fā)生錯誤該表單的errors即會有對應(yīng)的錯誤信息(如form.errors.username)。
當(dāng)我們提交表單的時候匙赞,視圖函數(shù)通過request.POST(如果提交方式為POST,為GET提交請使用request.GET),request.FILES(如果提交包含文件)自動創(chuàng)建好表單佛掖,然后調(diào)用is_valid()進(jìn)行驗證表單輸入,沒有錯誤則返回輸入信息涌庭,發(fā)生錯誤就返回表單提交頁面并顯示錯誤信息苦囱。
也許有人會說這種提交表單的方式過于笨重(在html模板中使用表單屬性),不夠靈活脾猛,有時候靈活和簡便是不可多得的,框架提供功能越多鱼鸠,可能導(dǎo)致其更為笨重猛拴,但是這里我們也可以不使用這種笨重的方式,我們只需要將html表單里屬性的name定義為和Form變量名一樣即可蚀狰,然后可以同樣在后臺創(chuàng)建接收輸入的表單愉昆,例如本例html代碼可以更改為
<form method="post" enctype="multipart/form-data" >
{%csrf_token%}
<p>username:<input id="id_username" maxlength="20" name="username" type="text" /></p>
<p>password:<input id="id_password" name="password" type="password" /></p>
<p>email:<input class="form-control" id="id_email" name="email" placeholder="email" type="text" /></p>
<P>headimage:<input id="id_image" name="image" type="file" /></P>
<input type="submit" value="Submit">
</form>
后臺視圖函數(shù)不需要任何更改也可正常使用。
對于Form驗證Django為我們提供了一些通用的驗證機(jī)制麻蹋,如驗證屬性是否為空(required),長度驗證(max_length,min_length),甚至電話號碼email驗證(EmailField,PhoneField)跛溉。
Form自定義驗證
form驗證流程
1.函數(shù)full_clean()依次調(diào)用每個field的clean()函數(shù),該函數(shù)針對field的max_length扮授,unique等約束進(jìn)行驗證芳室,如果驗證成功則返回值,否則拋出ValidationError錯誤刹勃。如果有值返回堪侯,則放入form的cleaned_data字典中。
2.如果每個field的內(nèi)置clean()函數(shù)沒有拋出ValidationError錯誤荔仁,則調(diào)用以clean_開頭伍宦,以field名字結(jié)尾的自定義field驗證函數(shù)芽死。驗證成功和失敗的處理方式同步驟1。
3.最后次洼,調(diào)用form的clean()函數(shù)——注意关贵,這里是form的clean(),而不是field的clean()——如果clean沒有錯誤,那么它將返回cleaned_data字典卖毁。
4.如果到這一步?jīng)]有ValidationError拋出揖曾,那么cleaned_data字典就填滿了有效數(shù)據(jù)。否則cleaned_data不存在势篡,form的另外一個字典errors填上驗證錯誤翩肌。在template中,每個field獲取自己錯誤的方式是:{{ form.username.errors }}禁悠。
5.最后念祭,如果有錯誤is_valid()返回False,否則返回True碍侦。
對于某些自定義驗證規(guī)則我們可以通過重載上述clean_field函數(shù)或者clean函數(shù)來實現(xiàn)粱坤,例如對于用戶注冊需要驗證用戶名是否存在,兩次密碼輸入是否相等瓷产,我們可以通過以下代碼實現(xiàn)
from django import forms
class RegisterForm(forms.Form):
username=forms.CharField(label='username',max_length=20,required=True,error_messages={'required':'username cannot be null'})
password=forms.CharField(label='password',widget=forms.PasswordInput,required=True,error_messages={'required':'password cannot be null'})
password1 = forms.CharField(label='password1', widget=forms.PasswordInput, required=True,
error_messages={'required': 'password cannot be null'})
email=forms.EmailField(label='email',required=True,
error_messages={'required': u'email cannot be null','invalid': u'email format is wrong'},
widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'email'}))
image=forms.ImageField(label='headimage',required=False)
def clean_username(self):
user = self.cleaned_data.get('username')
if user == 'cc':
raise forms.ValidationError('username exsite!')
return user
def clean(self):
cleaned_data = self.cleaned_data
pwd = cleaned_data['password']
pwd2 = cleaned_data['password1']
print(pwd, pwd2)
if pwd != pwd2:
raise forms.ValidationError('the password you input is not same')
return cleaned_data
我們重載clean_username函數(shù)來判斷提交用戶名是否為‘cc’站玄,如果相等則驗證失敗并提示錯誤(通過 raise forms.ValidationError('username exsite!')來實現(xiàn)),然后重載clean函數(shù)來判斷兩次輸入密碼是否相同濒旦。
Form文件接收
在上述例子中雖然使用了ImageField株旷,但是并沒有演示如何在視圖函數(shù)中接收文件,對于文件來說我們同樣可以通過form.cleaned_data['image']來獲取尔邓,然后可以獲取上傳文件的信息和實際文件并可以保存下來晾剖,代碼如下:
myFile=register_form.cleaned_data['image']
destination = open(os.path.join(BASE_DIR, myFile.name), 'wb+')
for chunk in myFile.chunks():
destination.write(chunk)
destination.close()
和前一節(jié)的文件提交類似。
經(jīng)過本節(jié)梯嗽,我們了解了Form的基本使用--創(chuàng)建齿尽,渲染以及數(shù)據(jù)驗證,其實Form的功能遠(yuǎn)不止于此灯节,在后面我們會發(fā)現(xiàn)和Model結(jié)合Form具有更強(qiáng)大的功能循头,你只需要少量代碼即可完成大量功能,這就是Django這種集大成框架的優(yōu)勢(當(dāng)然會損失點靈活性)炎疆,甚至就是python的宗旨(life is short,you need python)卡骂,今天我們先了解到這里,謝謝大家支持磷雇。
參考鏈接
1.https://www.cnblogs.com/ccorz/p/5868380.html
最近參加支付寶小程序比賽需要訪問量偿警,麻煩各位看官有空復(fù)制下面的話打開支付寶,搜索欄粘貼唯笙,在此多謝各位支持了
#JvCmawp74I1#長按復(fù)制此消息螟蒸,打開支付寶搜索盒使,體驗?zāi)暇┮咔榈貓D小程序