這篇文章主要介紹了在Django的視圖中使用form對象的方法,Django是Python豐富多彩的開發框架中最具有人氣的一個,需要的朋友可以參考下
在學習了關于Form類的基本知識后,你會看到我們如何把它用到視圖中,取代contact()代碼中不整齊的部分。 一下示例說明了我們如何用forms框架重寫contact():
- # views.py
- from django.shortcuts import render_to_response
- from mysite.contact.forms import ContactForm
- def contact(request):
- if request.method == 'POST':
- form = ContactForm(request.POST)
- if form.is_valid():
- cd = form.cleaned_data
- send_mail(
- cd['subject'],
- cd['message'],
- cd.get('email', 'noreply@example.com'),
- ['siteowner@example.com'],
- )
- return HttpResponseRedirect('/contact/thanks/')
- else:
- form = ContactForm()
- return render_to_response('contact_form.html', {'form': form})
- # contact_form.html
- <html>
- <head>
- <title>Contact us</title>
- </head>
- <body>
- <h1>Contact us</h1>
- {% if form.errors %}
- <p style="color: red;">
- Please correct the error{{ form.errors|pluralize }} below.
- </p>
- {% endif %}
- <form action="" method="post">
- <table>
- {{ form.as_table }}
- </table>
- <input type="submit" value="Submit">
- </form>
- </body>
- </html>
看看,我們能移除這么多不整齊的代碼! Django的forms框架處理HTML顯示、數據校驗、數據清理和表單錯誤重現。
嘗試在本地運行。 裝載表單,先留空所有字段提交空表單;繼而填寫一個錯誤的郵箱地址再嘗試提交表單;最后再用正確數據提交表單。 (根據服務器的設置,當send_mail()被調用時,你將得到一個錯誤提示。而這是另一個問題。)
改變字段顯示
你可能首先注意到:當你在本地顯示這個表單的時,message字段被顯示成`` input type=”text”`` ,而它應該被顯示成<`` textarea`` >。我們可以通過設置* widget* 來修改它:
- from django import forms
- class ContactForm(forms.Form):
- subject = forms.CharField()
- email = forms.EmailField(required=False)
- message = forms.CharField(**widget=forms.Textarea** )
forms框架把每一個字段的顯示邏輯分離到一組部件(widget)中。 每一個字段類型都擁有一個默認的部件,我們也可以容易地替換掉默認的部件,或者提供一個自定義的部件。
考慮一下Field類表現* 校驗邏輯* ,而部件表現* 顯示邏輯* 。
設置最大長度
一個最經常使用的校驗要求是檢查字段長度。 另外,我們應該改進ContactForm,使subject限制在100個字符以內。 為此,僅需為CharField提供max_length參數,像這樣:
- from django import forms
- class ContactForm(forms.Form):
- subject = forms.CharField(**max_length=100** )
- email = forms.EmailField(required=False)
- message = forms.CharField(widget=forms.Textarea)
選項min_length參數同樣可用。
設置初始值
讓我們再改進一下這個表單:為字subject段添加* 初始值* : "I love your site!" (一點建議,但沒壞處。)為此,我們可以在創建Form實體時,使用initial參數:
- def contact(request):
- if request.method == 'POST':
- form = ContactForm(request.POST)
- if form.is_valid():
- cd = form.cleaned_data
- send_mail(
- cd['subject'],
- cd['message'],
- cd.get('email', `'noreply@example.com`_'),
- [`'siteowner@example.com`_'],
- )
- return HttpResponseRedirect('/contact/thanks/')
- else:
- form = ContactForm(
- **initial={'subject': 'I love your site!'}**
- )
- return render_to_response('contact_form.html', {'form': form})
現在,subject字段將被那個句子填充。
請注意,傳入* 初始值* 數據和傳入數據以* 綁定* 表單是有區別的。 最大的區別是,如果僅傳入* 初始值* 數據,表單是unbound的,那意味著它沒有錯誤消息。
自定義校驗規則
假設我們已經發布了反饋頁面了,email已經開始源源不斷地涌入了。 這里有一個問題: 一些提交的消息只有一兩個字,我們無法得知詳細的信息。 所以我們決定增加一條新的校驗: 來點專業精神,最起碼寫四個字,拜托。
我們有很多的方法把我們的自定義校驗掛在Django的form上。 如果我們的規則會被一次又一次的使用,我們可以創建一個自定義的字段類型。 大多數的自定義校驗都是一次性的,可以直接綁定到form類.
我們希望`` message`` 字段有一個額外的校驗,我們增加一個`` clean_message()`` 方法到`` Form`` 類:
- from django import forms
- class ContactForm(forms.Form):
- subject = forms.CharField(max_length=100)
- email = forms.EmailField(required=False)
- message = forms.CharField(widget=forms.Textarea)
- def clean_message(self):
- message = self.cleaned_data['message']
- num_words = len(message.split())
- if num_words < 4:
- raise forms.ValidationError("Not enough words!")
- return message
Django的form系統自動尋找匹配的函數方法,該方法名稱以clean_開頭,并以字段名稱結束。 如果有這樣的方法,它將在校驗時被調用。
特別地,clean_message()方法將在指定字段的默認校驗邏輯執行* 之后* 被調用。(本例中,在必填CharField這個校驗邏輯之后。)因為字段數據已經被部分處理,所以它被從self.cleaned_data中提取出來了。同樣,我們不必擔心數據是否為空,因為它已經被校驗過了。
我們簡單地使用了len()和split()的組合來計算單詞的數量。 如果用戶輸入字數不足,我們拋出一個forms.ValidationError型異常。這個異常的描述會被作為錯誤列表中的一項顯示給用戶。
在函數的末尾顯式地返回字段的值非常重要。 我們可以在我們自定義的校驗方法中修改它的值(或者把它轉換成另一種Python類型)。 如果我們忘記了這一步,None值就會返回,原始的數據就丟失掉了。
指定標簽
HTML表單中自動生成的標簽默認是按照規則生成的:用空格代替下劃線,首字母大寫。如email的標簽是"Email" 。(好像在哪聽到過? 是的,同樣的邏輯被用于模塊(model)中字段的verbose_name值。 我們在第五章談到過。)
像在模塊中做過的那樣,我們同樣可以自定義字段的標簽。 僅需使用label,像這樣:
- class ContactForm(forms.Form):
- subject = forms.CharField(max_length=100)
- email = forms.EmailField(required=False, **label='Your e-mail address'** )
- message = forms.CharField(widget=forms.Textarea)
新聞熱點
疑難解答