Django學(xué)習(xí)筆記:Forms

表單介紹

HTML表單負(fù)責(zé)接收用戶的輸入,對輸入進(jìn)行合法格式判斷,并將數(shù)據(jù)發(fā)送到服務(wù)器。一個(gè)HTML表單必須指定兩樣?xùn)|西:發(fā)送數(shù)據(jù)的url地址,發(fā)送的HTTP方法(GET搞监、POST)水孩。

GET方法:將用戶數(shù)據(jù)以?<鍵1>=<值1>&<鍵2>=<值2>&...形式拼接到url后面,通常用于請求數(shù)據(jù)琐驴、網(wǎng)頁搜索的表單俘种。

POST方法:組合表單的數(shù)據(jù)并進(jìn)行編碼,然后打包發(fā)送到服務(wù)器绝淡,數(shù)據(jù)不會出現(xiàn)在url中宙刘,通常用于保密信息的發(fā)送、大量數(shù)據(jù)的表單牢酵、二進(jìn)制數(shù)據(jù)悬包。


在input標(biāo)簽中

#對于form表單也是一樣,如果前端不指定post方法馍乙,默認(rèn)使用get方法布近。



表單字段(常用)

CharField

渲染類型:TextInput

輸入空值的返回:empty_value設(shè)定的值

轉(zhuǎn)換為對象:Unicode對象

驗(yàn)證:min_length,max_length(如果設(shè)置過)

可用的錯(cuò)誤信息鍵:min_length丝格,max_length撑瞧,required

max_length:允許輸入的最大長度

min_length:允許輸入的最小長度

strip:默認(rèn)為True,表示去除前后的空格

empty_value:輸入為空時(shí)返回的值显蝌,默認(rèn)為空字符串


EmailField

渲染類型:EmailInput

輸入空值的返回:空字符串

轉(zhuǎn)換為對象:Unicode對象

驗(yàn)證:用正則表達(dá)式驗(yàn)證表單的值预伺,必須是合法郵件地址

可用的錯(cuò)誤信息鍵:required,invalid

max_length:允許輸入的最大長度

min_length:允許輸入的最小長度


表單字段的參數(shù)

error_messages

error_messages={‘key’: ‘value’}

自定義錯(cuò)誤提示信息,鍵是表單里同名的錯(cuò)誤類型字符串酬诀,值是自定義的提示信息字符串脏嚷。

其中的key包括:

required,無填寫內(nèi)容

invalid料滥,非法字符

maxlength然眼,超出長度上限


max_length

最大長度


min_length

最小長度


required

required=True/False

該字段必填/非必填。

當(dāng)為True時(shí)葵腹,<表單對象>.clean(‘‘)和<表單對象>.clean(None)返回ValidationError異常高每。

當(dāng)為False時(shí),<表單對象>.clean(‘‘)和<表單對象>.clean(None)返回None践宴。

?

label

label=’<顯示值>’

字段渲染成HTML代碼的提示詞鲸匿,默認(rèn)在后面加冒號。

如字段name = forms.CharField(label=’Your Name’)阻肩,顯示為HTML的

<label for=”id_name”>Your name:?</label>

<input id=”id_name”?type="text" name="name" required />


label_suffix

label_suffix=’<字符>’

自定義字符带欢,代替label生成顯示值后面的冒號。


initial

initial=’<值>’

為表單元素定義初始值烤惊,即標(biāo)簽中的value=乔煞,可傳入值和對象。

#?initial不會作為數(shù)據(jù)提交柒室,表單仍需要用戶填寫數(shù)據(jù)渡贾。

只能用initial傳遞初始值,如果在渲染表單的時(shí)候傳遞一個(gè)初始值字典雄右,會觸發(fā)表單的驗(yàn)證空骚,此時(shí)輸出的HTML頁面可能包含驗(yàn)證錯(cuò)誤。


widget

widget=<widget類>

指定渲染W(wǎng)idget時(shí)使用的widget類擂仍,即前端中的type類型囤屹。

可用attr參數(shù)傳入一個(gè)字典,對widget添加CSS樣式逢渔,如:

name = forms.CharField(widget=forms.TextInput(attrs={‘class’: ‘special’}) )

comment = forms.CharField(widget=forms.TextInput(attrs={‘size’: ‘40’}) )


help_text

help_text=’<文本>’

設(shè)定輔助性描述文本肋坚,相當(dāng)于HTML的默認(rèn)顯示值。


validators

validators=[ ]

傳入列表肃廓,包含對字段驗(yàn)證的函數(shù)冲簿,自定義驗(yàn)證方法的時(shí)候用。


localize

實(shí)現(xiàn)表單數(shù)據(jù)輸入的本地化亿昏。


disabled

disabled=True/False

設(shè)置對字段禁用/啟用編輯峦剔,禁用編輯后,即使非法篡改前端頁面的屬性向服務(wù)器提交角钩,該字段值也會被忽略吝沫。



表單API

綁定數(shù)據(jù)的表單能夠驗(yàn)證數(shù)據(jù)呻澜,然后生成HTML表單,未綁定的表單無法驗(yàn)證數(shù)據(jù)惨险,可生成HTML空表單羹幸。

創(chuàng)建空表單:f = <表單名>form()#創(chuàng)建表單類的實(shí)例

表單綁定數(shù)據(jù):data = {:}#字典鍵是表單的字段名,值是傳入的數(shù)據(jù)

? ? ? ? ? ? ? ? ? ? ? ? ? f = <表單名>form(data)

? ? ? ? ? ? ? ? ? ? ? ? ??#傳入空字典將創(chuàng)建一個(gè)數(shù)據(jù)為空的已綁定表單

forms.Form實(shí)例的數(shù)據(jù)無法自讀辫愉,所以創(chuàng)建表單對象之后不可更改栅受。


表單的綁定

<表單對象>.is_bound

判斷表單是/否綁定了數(shù)據(jù),返回True/False恭朗。


表單的數(shù)據(jù)錯(cuò)誤驗(yàn)證

<表單對象>.is_valid()

驗(yàn)證表單數(shù)據(jù)合法性屏镊,返回True/False。.is_valid()實(shí)際就是檢查<表單對象>.errors是否為空痰腮,如果errors列表為空而芥,就把所有數(shù)據(jù)儲存到<表單對象>.cleaned_data字典中。


<表單對象>.errors

包含所有錯(cuò)誤信息的字典類型膀值,鍵是表單字段名棍丐,值是由錯(cuò)誤信息組成的字符串形列表。


<表單對象>.errors.as_data()

返回錯(cuò)誤信息的字典形式沧踏,將字段映射到原始的ValidationError實(shí)例歌逢,如:

{'sender': [ValidationError(['Enter a valid email address.'])?],

'subject': [ValidationError(['This field is required.'])?]?}


<表單對象>.errors.as_json()

錯(cuò)誤信息字典的JSON序列化形式,如:

{"sender": [{"message": "Enter a valid email address.", "code": "invalid"}],

"subject": [{"message": "This field is required.", "code": "required"}]?}


<表單對象>.add_error(<字段名>, <錯(cuò)誤信息>)

向表單的指定字段添加錯(cuò)誤信息翘狱。


<表單對象>.has_error(<字段>, code=xxx)

判斷某個(gè)字段是/否有指定的xxx錯(cuò)誤秘案,返回True/False。當(dāng)code=None時(shí)盒蟆,該字段有任何錯(cuò)誤都返回True。


<表單對象>.non_field_errors()

返回<表單對象>.errors中不是與特定字段關(guān)聯(lián)的錯(cuò)誤师骗。

?

表單的cleaned_data數(shù)據(jù)

①如果數(shù)據(jù)驗(yàn)證通過历等,把所有數(shù)據(jù)儲存到<表單對象>.cleaned_data字典中;如果數(shù)據(jù)驗(yàn)證不通過辟癌,只把合法的數(shù)據(jù)存到<表單對象>.cleaned_data字典中寒屯。

②cleaned_data只包含F(xiàn)orm類中的字段,如果傳遞額外數(shù)據(jù)黍少,將不被儲存寡夹。

③傳遞的數(shù)據(jù)不包含F(xiàn)orm類中的某字段,cleaned_data中依然包含該鍵值對厂置,顯示為空值菩掏。


表單的數(shù)據(jù)更改驗(yàn)證

<表單對象>.has_changed()

檢查表單數(shù)據(jù)是否從初始值發(fā)生改變,有改變返回True昵济,無改變返回False智绸,如:

data = <字典>

f = ContactForm(request.POST, initial=data) ?????#?POST和data內(nèi)容不一樣

f.has_changed()


<表單對象>.changed_data

返回表單中有數(shù)據(jù)變化的字段的列表野揪,如:

f = ContactForm(request.POST, initial=data) ?????#?POST和data內(nèi)容不一樣

print(“, “.join(f.changed_data) )


表單的HTML生成

form類不包含<form></form>標(biāo)簽和<input type=”submit”>提交按鈕,為方便開發(fā)人員自行編寫控制表單動作和CSS瞧栗,JS及如bootstrap框架的嵌入斯稳。

生成HTML標(biāo)簽的就是表單字段名,每個(gè)字段類型都由一個(gè)默認(rèn)的HTML標(biāo)簽展示迹恐,可用widget參數(shù)指定生成的類型挣惰。

表單自動為每個(gè)input元素設(shè)置一個(gè),用于的for參數(shù)殴边。


{{ form.as_p }}

將每個(gè)字段渲染成標(biāo)簽憎茂。


{{ form.as_ul }}

將每個(gè)字段渲染成

標(biāo)簽(無序),

    標(biāo)簽需自己指定找都。


    {{ form.as_table }}

    將表單的每個(gè)字段渲染成標(biāo)簽唇辨,標(biāo)簽需自己指定。


    表單字段在前端的屬性

    {{ field.value }} ?? ?? 當(dāng)前字段的值能耻,比如一個(gè)Email字段的值:someone@example.com

    {{ field.errors }} ? ?? 包含錯(cuò)誤信息的元素

    {{ field.label }} ?? 字段的label信息

    {{ field.id_for_label }} 自定義字段標(biāo)簽的id

    {{ field.html_name }} 指定字段生成的input標(biāo)簽中name屬性的值

    {{ field.help_text }} 字段的幫助信息

    {{ field.is_hidden }} 用于判斷當(dāng)前字段是否為隱藏的字段赏枚,隱藏則返回True

    {{ field.field }} ? ?? 返回字段的參數(shù)列表,例如{{ char_field.field.max_length }}


    表單錯(cuò)誤信息的CSS樣式

    class <表單名>FORM(forms.Form):

    ????error_css_class = ‘error’

    ????required_css_class = ‘required’

    ? ??#其它表單字段...

    以后這個(gè)表單渲染HTML時(shí)將自動為error行和required行添加對應(yīng)的CSS樣式晓猛。


    表單上傳文件

    沒看懂饿幅,略。戒职。栗恩。



    模型表單ModelForm

    基于model模型創(chuàng)建的表單,對模型的字段進(jìn)行重用洪燥,根據(jù)model字段的限制進(jìn)行表單驗(yàn)證磕秤。

    驗(yàn)證后,ModelForm.save()實(shí)際就是調(diào)用Model.save()捧韵,直接保存到數(shù)據(jù)庫市咆。


    from django.forms import ModelForm

    from <應(yīng)用名>.models import <類>


    class <類名>Form(ModelForm): ??????#繼承于ModelForm類

    ????class Meta: ????????????????????#設(shè)置元類Meta

    ????????model = <類> ??????????????#設(shè)置model屬性為某個(gè)模型類

    ????????fields = [<字段1>, <字段2>, ...] ?????#用field屬性傳入列表,指定類中的字段

    ????????fields = ‘__all__’????????????????????#也可用field屬性傳入類的全部字段

    ????????exclude = [<字段1>, <字段2>, ...] ????#用exclude屬性將排除的字段之外全部傳入


    模型表單的保存

    <模型表單對象>.save(commit=True) ??????#將form表單的內(nèi)容提交到數(shù)據(jù)庫并保存

    如果沒有commit=True就只提交再来,不保存


    指定數(shù)據(jù)對象

    form = ModelForm(instance=<綁定的Model對象>)

    此時(shí)可以直接form.save()將表單數(shù)據(jù)保存到數(shù)據(jù)表中蒙兰。

    #如果不指定某個(gè)對象,save()時(shí)會在數(shù)據(jù)表中新增一行數(shù)據(jù)


    模型字段對應(yīng)表單字段

    Model???????????????????????????Form

    AutoField ???????????????????????無對應(yīng)

    BigAutoField ????????????????????無對應(yīng)

    BigIntegerField ??????????????????IntegerField

    CharField ???????????????????????相同芒篷,如果model設(shè)置null=True搜变,F(xiàn)orm將使用empty_value

    CommaSeparatedIntegerField ?????CharField

    ForeignKey ??????????????????????ModelChoiceField

    ManyToManyField ????????????????ModelMultipleChoiceField

    PositiveIntegerField ???????????????IntegerField

    PositiveSmallIntegerField ??????????IntegerField

    SmallIntegerField ?????????????????IntegerField

    TextField ?????????????????????????CharField,屬性widget=forms.Textarea

    模型字段設(shè)置blank=True屬性针炉,表單字段將設(shè)置required=False挠他,反之相反。

    模型字段的verbose_name屬性會設(shè)為表單字段的label屬性篡帕,并將第一個(gè)字母大寫绩社。

    模型字段設(shè)置editable=False屬性摔蓝,表單類中將不會出現(xiàn)該字段,因?yàn)樵撟侄尾豢删庉嫛?/p>

    模型字段的help_text屬性即為表單字段的help_text屬性愉耙。

    模型字段設(shè)置choices參數(shù)贮尉,表單字段的widget屬性將設(shè)置為Select,其選項(xiàng)和模型字段相同朴沿。表單選項(xiàng)中通常會包含一個(gè)空選項(xiàng)作為默認(rèn)猜谚,如果該字段必選,會強(qiáng)制用戶選擇一個(gè)選項(xiàng)赌渣;如果模型字段具有default參數(shù)魏铅,就不會在表單選項(xiàng)中添加空選項(xiàng)。


    模型表單的驗(yàn)證

    用.is_valid()方法或查詢.errors列表坚芜,也可以重寫模型表單的def clean()方法進(jìn)行額外的驗(yàn)證览芳,如:

    class <類名>Form(ModelForm):

    ????class meta:

    ? ??????#?...


    def clean_<函數(shù)名>(self):

    ? ??#驗(yàn)證self.cleaned_data字典的數(shù)據(jù)...

    ????return <數(shù)據(jù)>


    自定義ModelForm字段

    使用元類Meta的widgets屬性:

    class <類名>Form(ModelForm):

    ????class Meta:

    ????????model = <類>

    ????????fields = [‘<字段1>’, ...]

    ????????widgets = { ???????????????????????#傳入字典,鍵是模型字段名鸿竖,值是自定義的內(nèi)容

    ????????????‘<字段1>’:Textarea(attrs={‘cols’:80, ‘rows’:20} ),

    ????????????...

    ????????}


    ModelForm字段的本地化

    使用Meta類的localized_fields屬性沧竟,傳入一個(gè)元組,指定本地化的字段:

    class <類名>Form(ModelForm):

    class meta:

    ????model = <類>

    ????localized_fields = (‘<字段1>’, ...) ??????#傳入’__all__’表示將類中的所有字段本地化




    表單示例

    ①在forms.py中:

    from django import forms


    class <表單名>Form(forms.Form): ????#所有表單繼承于forms.Form類

    ????sender = forms.EmailField()

    ????name = forms.CharField(label=’Your Name’, max_length=100)

    ? ??#一個(gè)字段代表中的一個(gè)元素缚忧,字段負(fù)責(zé)驗(yàn)證和轉(zhuǎn)換數(shù)據(jù)

    ? ??#?label用于設(shè)置說明標(biāo)簽悟泵,這里的max_length同時(shí)限制前端和后端的輸入長度


    ②在views.py中:

    from .forms import <表單名>Form


    def get_name(request):

    ????if request.method == ’POST’: ?????????#對于POST方法發(fā)送數(shù)據(jù),接收數(shù)據(jù)并驗(yàn)證闪水、處理

    ????a_form = <表單名>Form(request.POST)

    ? ??#用request.POST字典構(gòu)造forms.Form類實(shí)例糕非,將所有數(shù)據(jù)加載到表單中

    ????????if a_form.is_valid():

    ? ??????????#處理表單數(shù)據(jù)...

    ????????????return HttpResponseRedirect(‘/xxx/’) ???#處理成功,重定向到一個(gè)新url

    ????if request.method == ’GET’: ????????????????#對于GET方法請求數(shù)據(jù)球榆,返回空表單到模板

    ????????a_form = <表單名>Form()


    ????return render(request, ‘xxx.html’, {‘form’: a_form}

    #處理不成功時(shí)朽肥,給用戶返回這個(gè)模板。如果數(shù)據(jù)不合法持钉,邏輯會在if a_form.is_valid()處斷開衡招,

    此時(shí)的a_form是包含原數(shù)據(jù)的表單,方便用戶修改


    ③在templates中:

    <form action="/xxx/" method="post">??????????#寫標(biāo)簽

    ????{% csrf_token %}

    ????{{ form }}?????????????????????????????????#表單模型生成的form表單元素

    ????<input type="submit" value="Submit" />??????#寫提交按鈕

    </form>


    {{ form.<字段名> }} ?????????????獲取表單的字段內(nèi)容右钾,用于手動渲染表單

    {{ form.<字段名>.label_tag }} ?????生成<label>標(biāo)簽蚁吝,用于手動渲染表單

    {{ form.hidden_fields }} ??????????表單中的不可見字段的集合

    {{ form.visible_fields }} ???????????表單中的可見字段的集合




    表單模板的重用

    將表單模板保存為一個(gè)獨(dú)立HTML文件旱爆,然后用{% include %}引用:

    {% include ‘xxxform.html’?%}

    {% for field in form %}

    ? ??#處理字段...

    {% endfor %}


    用with參數(shù)給表單取別名舀射,防止名稱沖突:

    {% include ‘xxxform.html’?with form=<別名> %}

    {% for field in <別名> %}

    ? ??#處理字段...

    {% endfor %}

    ?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
    • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市怀伦,隨后出現(xiàn)的幾起案子脆烟,更是在濱河造成了極大的恐慌,老刑警劉巖房待,帶你破解...
      沈念sama閱讀 211,290評論 6 491
    • 序言:濱河連續(xù)發(fā)生了三起死亡事件邢羔,死亡現(xiàn)場離奇詭異驼抹,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)拜鹤,發(fā)現(xiàn)死者居然都...
      沈念sama閱讀 90,107評論 2 385
    • 文/潘曉璐 我一進(jìn)店門框冀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人敏簿,你說我怎么就攤上這事明也。” “怎么了惯裕?”我有些...
      開封第一講書人閱讀 156,872評論 0 347
    • 文/不壞的土叔 我叫張陵温数,是天一觀的道長。 經(jīng)常有香客問我蜻势,道長撑刺,這世上最難降的妖魔是什么? 我笑而不...
      開封第一講書人閱讀 56,415評論 1 283
    • 正文 為了忘掉前任握玛,我火速辦了婚禮够傍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘败许。我一直安慰自己王带,他們只是感情好,可當(dāng)我...
      茶點(diǎn)故事閱讀 65,453評論 6 385
    • 文/花漫 我一把揭開白布市殷。 她就那樣靜靜地躺著愕撰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪醋寝。 梳的紋絲不亂的頭發(fā)上搞挣,一...
      開封第一講書人閱讀 49,784評論 1 290
    • 那天,我揣著相機(jī)與錄音音羞,去河邊找鬼囱桨。 笑死,一個(gè)胖子當(dāng)著我的面吹牛嗅绰,可吹牛的內(nèi)容都是我干的舍肠。 我是一名探鬼主播,決...
      沈念sama閱讀 38,927評論 3 406
    • 文/蒼蘭香墨 我猛地睜開眼窘面,長吁一口氣:“原來是場噩夢啊……” “哼翠语!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起财边,我...
      開封第一講書人閱讀 37,691評論 0 266
    • 序言:老撾萬榮一對情侶失蹤肌括,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后酣难,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谍夭,經(jīng)...
      沈念sama閱讀 44,137評論 1 303
    • 正文 獨(dú)居荒郊野嶺守林人離奇死亡黑滴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
      茶點(diǎn)故事閱讀 36,472評論 2 326
    • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了紧索。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片袁辈。...
      茶點(diǎn)故事閱讀 38,622評論 1 340
    • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖珠漂,靈堂內(nèi)的尸體忽然破棺而出吵瞻,到底是詐尸還是另有隱情,我是刑警寧澤甘磨,帶...
      沈念sama閱讀 34,289評論 4 329
    • 正文 年R本政府宣布橡羞,位于F島的核電站,受9級特大地震影響济舆,放射性物質(zhì)發(fā)生泄漏卿泽。R本人自食惡果不足惜,卻給世界環(huán)境...
      茶點(diǎn)故事閱讀 39,887評論 3 312
    • 文/蒙蒙 一滋觉、第九天 我趴在偏房一處隱蔽的房頂上張望签夭。 院中可真熱鬧,春花似錦椎侠、人聲如沸第租。這莊子的主人今日做“春日...
      開封第一講書人閱讀 30,741評論 0 21
    • 文/蒼蘭香墨 我抬頭看了看天上的太陽慎宾。三九已至,卻和暖如春浅悉,著一層夾襖步出監(jiān)牢的瞬間趟据,已是汗流浹背。 一陣腳步聲響...
      開封第一講書人閱讀 31,977評論 1 265
    • 我被黑心中介騙來泰國打工术健, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留汹碱,地道東北人。 一個(gè)月前我還...
      沈念sama閱讀 46,316評論 2 360
    • 正文 我出身青樓荞估,卻偏偏與公主長得像咳促,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子勘伺,可洞房花燭夜當(dāng)晚...
      茶點(diǎn)故事閱讀 43,490評論 2 348

    推薦閱讀更多精彩內(nèi)容

    • 在上一個(gè)章節(jié)跪腹,我們已經(jīng)創(chuàng)建了一個(gè)基礎(chǔ)的Blog程序。現(xiàn)在我們將使用一些Dajngo高級功能娇昙,去實(shí)現(xiàn)一個(gè)完整的blo...
      金金剛狼閱讀 3,578評論 1 12
    • 要實(shí)現(xiàn)下圖所示的申請表單尺迂。其中: ? 學(xué)校名稱笤妙、聯(lián)系電話必填冒掌; ? 學(xué)校地址噪裕、聯(lián)系人、郵箱選填股毫; ? ...
      學(xué)以致用123閱讀 876評論 3 6
    • forms.py 表單模板 from django import forms from mysite import...
      陸文斌閱讀 246評論 0 0
    • 心想雪花已飛舞膳音, 我應(yīng)去踏雪尋梅。 都知天公難做美铃诬, 豈料天下已無梅祭陷。 心中憂煩自然多, 卻不敢借酒銷愁趣席。
      闌珊處看下雨閱讀 164評論 0 1
    • 當(dāng)我的胡須還未如今堅(jiān)硬兵志,當(dāng)我的右臂還未如此強(qiáng)壯,當(dāng)我到腦中還未植入日本女人的叫聲宣肚。那些年還沒有在自己的西西里遇到m...
      Luimmmm閱讀 946評論 1 3