django book2 表單學習筆記

form = ProductForm(request.POST or None):python or 含義:如果第1個爲真,返回第1個,否則返回第2個


def search(request):
    **errors = []**
    if 'q' in request.GET:
        q = request.GET['q']
        if not q:
            **errors.append('Enter a search term.')**
        elif len(q) > 20:
            **errors.append('Please enter at most 20 characters.'
        else:
            books = Book.objects.filter(title__icontains=q)
            return render_to_response('search_results.html',
                {'books': books, 'query': q})
    return render_to_response('search_form.html',
        {**'errors': errors** })






from django.core.mail import send_mail
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
def contact(request):
    errors = []
    if request.method == 'POST':
        if not request.POST.get('subject', ''):
            errors.append('Enter a subject.')
        if not request.POST.get('message', ''):
            errors.append('Enter a message.')
        if request.POST.get('email') and '@' not in request.POST['email']:
            errors.append('Enter a valid e‐mail address.')
        if not errors:
            send_mail(
                request.POST['subject'],
                request.POST['message'],
                request.POST.get('email', '[email protected]'),
                ['[email protected]'],
            )
            return HttpResponseRedirect('/contact/thanks/')
    return render_to_response('contact_form.html',
        {'errors': errors})
        
當郵件發送成功之後,我們使用HttpResponseRedirect對象將網頁重定向至一個包含成功信息的頁面。 包
含成功信息的頁面這裏留給讀者去編寫(很簡單 一個視圖/URL映射/一份模板即可),但是我們要解釋一
下爲何重定向至新的頁面,而不是在模板中直接調用render_to_response()來輸出。


原因就是: 若用戶刷新一個包含POST表單的頁面,那麼請求將會重新發送造成重複。 這通常會造成非期望
的結果,比如說重複的數據庫記錄;在我們的例子中,將導致發送兩封同樣的郵件。 如果用戶在POST表單
之後被重定向至另外的頁面,就不會造成重複的請求了。
我們應每次都給成功的POST請求做重定向。 這就是web開發的最佳實踐。




1)Python解釋器裏面看看這個類做了些什麼。 它做的第一件事是將自己顯示成HTML:
>>> from contact.forms import ContactForm
>>> f = ContactForm()
>>> print f
<tr><th><label for="id_subject">Subject:</label></th><td><input type="text" name="subject" id="id_
<tr><th><label for="id_email">Email:</label></th><td><input type="text" name="email" id="id_email"
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_




Form對象做的第二件事是校驗數據。 爲了校驗數據,我們創建一個新的對Form象,並且傳入一個與定義匹配的
字典類型數據:
>>> f = ContactForm({'subject': 'Hello', 'email': '[email protected]', 'message': 'Nice site!'})
一旦你對一個Form實體賦值,你就得到了一個綁定form:
>>> f.is_bound
obook.py3k.cn/2.0/chapter07/12/182010-5-5第七章:表單
True
調用任何綁定form的is_valid()方法,就可以知道它的數據是否合法。 我們已經爲每個字段傳入了值,因此整
個Form是合法的:
>>> f.is_valid()
True




每一個邦定Form實體都有一個errors屬性,它爲你提供了一個字段與錯誤消息相映射的字典表。
>>> f = ContactForm({'subject': 'Hello', 'message': ''})
>>> f.errors
{'message': [u'This field is required.']}


最終,如果一個Form實體的數據是合法的,它就會有一個可用的cleaned_data屬性。 這是一個包含乾淨的提交
數據的字典。 Django的form框架不但校驗數據,它還會把它們轉換成相應的Python類型數據,這叫做清理數
據。
>>> f = ContactForm({subject': Hello, email: [email protected], message: Nice site!})
>>> f.is_valid()
True
>>> f.cleaned_data
{message': uNice site!, email: [email protected], subject: uHello}








在視圖中使用Form對象


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', '[email protected]'),
                ['[email protected]'],
            )
            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顯示、數據校驗、數據清理和表單錯
誤重現。




1 改變字段顯示
    你可能首先注意到:當你在本地顯示這個表單的時,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** )
    obook.py3k.cn/2.0/chapter07/14/182010-5-5第七章:表單
    forms框架把每一個字段的顯示邏輯分離到一組部件(widget)中。 每一個字段類型都擁有一個默認的部件,
    我們也可以容易地替換掉默認的部件,或者提供一個自定義的部件。
    考慮一下Field類表現* 校驗邏輯* ,而部件表現* 顯示邏輯* 。
2 設置最大長度
    一個最經常使用的校驗要求是檢查字段長度。 另外,我們應該改進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參數同樣可用。
3 設置初始值
    讓我們再改進一下這個表單:爲字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', `'[email protected]`_'),
                    [`'[email protected]`_'],
                )
                return HttpResponseRedirect('/contact/thanks/')
        else:
            form = ContactForm(
                **initial={'subject': 'I love your site!'}**
            )
        return render_to_response('contact_form.html', {'form': form})
    現在,subject字段將被那個句子填充。
    請注意,傳入* 初始值* 數據和傳入數據以* 綁定* 表單是有區別的。 最大的區別是,如果僅傳入* 初始值* 數
    據,表單是unbound的,那意味着它沒有錯誤消息。
4 自定義校驗規則
    假設我們已經發布了反饋頁面了,email已經開始源源不斷地涌入了。 這裏有一個問題: 一些提交的消息只有
    一兩個字,我們無法得知詳細的信息。 所以我們決定增加一條新的校驗: 來點專業精神,最起碼寫四個字,拜
    託。
    我們有很多的方法把我們的自定義校驗掛在Django的form上。 如果我們的規則會被一次又一次的使用,我們
    可以創建一個自定義的字段類型。 大多數的自定義校驗都是一次性的,可以直接綁定到form類.
    djangobook.py3k.cn/2.0/chapter07/15/182010-5-5第七章:表單
    我們希望`` message`` 字段有一個額外的校驗,我們增加一個`` clean_message()`` 方法到`` Form`` 類:
    1from 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值就會返回,原始的數據就丟失掉了。
    
 5 指定標籤
    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)
        
        
6 定製Form設計
    在上面的`` contact_form.html`` 模板中我們使用`` {{form.as_table}}`` 顯示錶單,不過我們可以使用其他更精
    確控制表單顯示的方法。
    修改form的顯示的最快捷的方式是使用CSS。 尤其是錯誤列表,可以增強視覺效果。自動生成的錯誤列表精確
    的使用`` <ul class=”errorlist”>``,這樣,我們就可以針對它們使用CSS。 下面的CSS讓錯誤更加醒目了:
    <style type="text/css">
        ul.errorlist {
            margin: 0;
            padding: 0;
        }
        .errorlist li {
            background‐color: red;
            display: block;
            font‐size: 10px;
            margin: 0 0 3px;
            padding: 4px 5px;
        }
    </style>
    雖然,自動生成HTML是很方便的,但是在某些時候,你會想覆蓋默認的顯示。 {{form.as_table}}和其它的方
    法在開發的時候是一個快捷的方式,form的顯示方式也可以在form中被方便地重寫。
    每一個字段部件(<input type=”text”>, <select>, <textarea>, 或者類似)都可以通過訪問{{form.字段名}}進
    行單獨的渲染。
    <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">
            <div class="field">
                {{ form.subject.errors }}
                <label for="id_subject">Subject:</label>
                {{ form.subject }}
            </div>
            <div class="field">
                {{ form.email.errors }}
                <label for="id_email">Your e‐mail address:</label>
                {{ form.email }}
            </div>
            <div class="field">
                {{ form.message.errors }}
                <label for="id_message">Message:</label>
                {{ form.message }}
            </div>
            <input type="submit" value="Submit">
        </form>
    </body>
    </html>
    {{ form.message.errors }} 會在 <ul class="errorlist"> 裏面顯示,如果字段是合法的,或者form沒有被綁
    定,就顯示一個空字符串。 我們還可以把 form.message.errors 當作一個布爾值或者當它是list在上面做迭代,
    例如:
    <div class="field{% if form.message.errors %} errors{% endif %}">
        {% if form.message.errors %}
            <ul>
            {% for error in form.message.errors %}
                <li><strong>{{ error }}</strong></li>
            {% endfor %}
            </ul>
        {% endif %}
        <label for="id_message">Message:</label>


    Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
    This work is licensed under the GNU Free Document License. 
    Hosting graciously provided by  
    Chinese translate hosting by py3k.cn.
    Document License`_.
        {{ form.message }}
    </div>
    在校驗失敗的情況下, 這段代碼會在包含錯誤字段的div的class屬性中增加一個”errors”,在一個有序列表中
    顯示錯誤信息。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章