(5)Django框架學習-Forms篇


Forms

HTML form是交互網頁的支柱。下面來學習一下有關使用Django處理用戶提交的表單數據,驗證等功能。
我們將討論HttpRequest和Form對象。
  • request中包含的信息
在views.py中的每一個用於顯示頁面的函數都需要以request作為第一個函數參數。request包含了一些有用
的信息,如:
request.path               除去了域名和端口的訪問路徑,
request.get_host       域名+端口信息
request.get_full_path()   所有路徑,包含傳遞的參數
requets.is_secure()     是否使用https進行鏈接
還有一個特別的屬性request.META,它是一個dict類型,包含了所有HTTP header信息,不過也要根據用戶
的實際環境來決定。如
HTTP_REFERER
HTTP_USER_AGENT   用戶使用的瀏覽器信息
REMOTE_ADDR     用戶的IP,如果使用代理,也可以顯示出來
(有很多屬性,只是截圖了一些)
  
並不是每一個用戶提交的頭信息都相同,所以在讀取的時候,要考慮一些異常情況,比如取不到相應的值的情況。
可以使用try...except,也可以使用dict.get(key, default)中默認返回為預設值的方法。
def ua_display_good1(request):
    try:
        ua = request.META['HTTP_USER_AGENT']
    except KeyError:
        ua = 'unknown'
    return HttpResponse("Your browser is %s" % ua)
 
def ua_display_good2(request):
    ua = request.META.get('HTTP_USER_AGENT', 'unknown')
    return HttpResponse("Your browser is %s" % ua)
 
除了以上的這些元數據的信息,HttpRequest對象還包括兩個屬性包括了用戶提交的數據:
request.GET和request.POST。它們都是dictionary-like對象。意思就是說可以像dict那樣
操作,但不是dict,還有一些dict沒有的操作。
 
下面構造一個用於用戶搜索的簡單form例子。
#template/search_form.html
< form action= "/search/" method= "get">
    < input type= "text" name= "q">
    < input type= "submit" value= "Search">
</ form>
#template/search_results.html
< p>Your searched for '{{ query }}'
{% if books %}
    {% for book in books %}
        < li>{{ book. title }}</ li>
    {% endfor %}
{% else %}
    < p>No books found.
{% endif %}
# urls.py
from django.conf.urls import patterns, include, url
from books.views import hello, search_form, search
urlpatterns = patterns( '',
    url(r '^search-form/$', search_form),
    url(r '^search/$', search),                     
)
#views.py
from django.http import HttpResponse
from django.shortcuts import render_to_response
from books.models import Book

def search_form(request) :
     return render_to_response( 'search_form.html')

def search(request) :
     if 'q' in request.GET : #GET是一個dict,使用文本框的name作為key
     #在這里需要做一個判斷,是否存在提交數據,以免報錯
        q = request.GET[ 'q']
         #使用lookup后綴,意思為書名不區分大小寫,包含q就可以
        books = Book.objects. filter(title__icontains =q)
         return render_to_response( 'search_results.html', { 'books' : books, 'query' :q})
     else :
        message = 'You submitted an empty form.'
         #只是簡單的返回一個response對象,因為沒有使用模塊,所以也不用渲染數據Context
         return HttpResponse(message)
 
還有一點,form中的action屬性如果為空的,代表提交數據到當前頁面。    
 
關於表單驗證
可以在server端進行,有時會加重server負擔,也可以使用Javascript在client端進行。有一點需要注意的是,
即使你使用了javascript在client進行了驗證,還是需要在server端對用戶提交的數據進行審查,比如有些人
會在瀏覽器中禁用javascript,也有些人會來搞注入攻擊。總之,不能相信用戶提交的提交,進行防御性編碼。
 
關於使用重定向
你應當總是在一個成功處理POST請求之后進行redirect,這樣可以避免用戶多次點擊提交按鈕帶來的二次請求
問題,有時會造成不好的后果,如向數據庫插入重復記錄等。
from django.http import HttpResponseRedirect
return HttpResponseRedirect('/success/')
  • 使用Django的form system來簡化表單工作
在app文件夾下創建forms.py,其實在哪里創建都可以:
from django import forms
 
class ContactForm(forms.Form):
    subject = forms.CharField()
    email = forms.EmailField(required=False)
    message = forms.CharField()
form的定義和model類的定義很像。我們可以使用python manage.py shell來查看form類的信息。
 
可以看到打印出來的f的信息其實是網頁格式的。
也可以改變默認表格的格式。
 
這里的<table>,<ul>都沒有包含在輸出里,所以可以自由地添加行等。
除了打印出整個form的HTML內容,還可以打印出局的字段的內容。
 
 
還可以使用form類進行驗證,使用dict對form類進行初始化。
>>> f = ContactForm({'subject': 'Hello', 'email': 'adrian@example.com', 'message': 'Nice'})
>>> f.is_bound #是否綁定表單類
True
>>> f.is_valid() #數據內容是否合法
True
當數據全部合法時,可以使用clean_data這個屬性,用來得到經過'clean'格式化的數據,會所提交過
來的數據轉化成合適的Python的類型。
 
如何在view中使用form類
# views.py

from django.shortcuts import render_to_response
from mysite.contact.forms import ContactForm

def contact(request) :
    #可以不寫,因為python中if中定義的變量,也可以在整個函數中可見    
    form = None 
     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/') #需要在urls.py中配置路徑
     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;">
            {# pulralize 是filter,用來判斷是否為添加's'來表示單詞的復數形式#}
            Please correct the error{{ form.errors|pluralize }} below.
        </ p>
    {% endif %}

    < form action= "" method= "post">
        < table>
            {# 可以使用as_ul, as_p來改變格式 #}
            {{ form.as_table }}
        </ table>
        < input type= "submit" value= "Submit">
    </ form>
</ body>
</ html>
 
在構造form的時候,還可以改變字段的構造參數
class ContactForm(forms.Form) :
    subject = forms.CharField(max_length = 100)
    email = forms.EmailField(required = False)
    message = forms.CharField(widget =forms.Textarea)
還可以給form類添加默認值
form = ContactForm(
            initial={'subject': 'I love your site!'}
        )
 
給form類自定義驗證規則,如果想要重用驗證機制,可以單獨創建新的字段類,重新寫它的驗證方法。
一般的可以直接在form類加入clean_字段名的方法,Django會自動查找以clean_開頭的函數名,並會在
驗證該字段的時候,運行這個函數。
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
在自定義的驗證函數中,我們必須顯示的返回字段名的內容,否則會帶來表單數據丟失。
 
可以改變字段的label顯示的名稱
email = forms.EmailField(required=False, label='Your e-mail address')
 






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM