表單是交互性網站的支柱。javascript
本文內容包括django對錶單提交數據的訪問,有效性檢查以及其餘處理,還有HttpRequest對象和Form對象。css
定義views.pyhtml
def current_url_view(request): return HttpResponse("Welcome to the page at %s,host is %s,full path is %s,is_secure is %s" % (request.path,request.get_host(),request.get_full_path(),request.is_secure()))
能夠顯示出:前端
Welcome to the page at /url/,host is 10.1.101.227:9000,full path is /url/,is_secure is False
顯示全部META,在views.py裏增長函數display_meta。java
def display_meta(request): values = request.META.items() values.sort() html = [] for k, v in values: html.append('<tr><td>%s</td><td>%s</td></tr>' % (k, v)) return HttpResponse('<table>%s</table>' % '\n'.join(html))
POST數據是來自form表單提交的,GET數據可能來自form表單也可能來自url。python
當提交表單僅僅須要獲取數據就使用GET,當提交表單須要更改服務器數據的狀態或者發e-mail,或者其餘不只僅是獲取顯示數據的狀況就使用POST。linux
判斷request.method的值能很好的幫助咱們將表單顯示[GET]與表單處理[POST]隔離開來。程序員
仍是以書籍、做者、出版商爲例。web
表單的開發分爲兩個部分:前端HTML頁面用戶接口和後臺view函數對所提交數據的處理過程。shell
首先創建前端html頁面接口,即經過創建一個view來顯示一個搜索表單,涉及三個文件:
urls.py
from books.views import * urlpatterns = patterns('', # ... (r'^search-form/$', search_form), # ... )
views.py
liuxiaoyan@development:~/mysite/books$ cat views.py # Create your views here. from django.shortcuts import render_to_response def search_form(request): return render_to_response('search_form.html')
search_form.html模板
liuxiaoyan@development:~/mysite$ cat templates/search_form.html <html> <head> <title>Search</title> </head> <body> <form action="/search/" method="get"> <input type="text" name="q"> <input type="submit" value="Search"> </form> </body> </html>
如今訪問/search-form/,能夠看到一個簡單的搜索界面。你真正經過該form表單提交數據查找時會404,由於form指向的URL/search/尚未實現。如今實現。
添加第二個視圖函數並設置URL。
urls.py
liuxiaoyan@development:~/mysite$ cat urls.py from django.conf.urls.defaults import patterns, include, url from views import * from books.views import * urlpatterns = patterns('', (r'^search-form/$',search_form), (r'^search/$',search), )
views.py
liuxiaoyan@development:~/mysite/books$ cat views.py # Create your views here. from django.shortcuts import render_to_response from django.http import HttpResponse def search_form(request): return render_to_response('search_form.html') def search(request): if 'q' in request.GET: message='You searched for : %r ' % request.GET['q'] else: message='You submitted an empty form.' return HttpResponse(message)
如今就能夠顯示用戶搜索的詞。咱們能夠看到搜索數據在django中的傳遞。
a、在html裏定義了一個變量q,當表單提交時,變量q的值經過GET(method="get")附加在URL/search/上。
b、處理/search/的視圖經過request.GET來獲取q的值。明確判斷過q是否包含在request.GET中。
修改search視圖。
liuxiaoyan@development:~/mysite/books$ cat views.py # Create your views here. from django.shortcuts import render_to_response from django.http import HttpResponse from books.models import Book #記得導入Book def search_form(request): return render_to_response('search_form.html') def search(request): if 'q' in request.GET and request.GET['q']: #判斷q是否存在於requests.GET而且request.GET['q']是否爲空 q = request.GET['q'] books = Book.objects.filter(title__icontains=q)#獲取數據庫中包含q的書籍,icontains是一個查詢關鍵字,不區分大小寫 return render_to_response('search_results.html', {'books': books, 'query': q})#給模板傳遞一個Book對象列表 else: return HttpResponse('Please submit a search term.')
Note:大量數據的數據庫不建議用icontains查詢,由於很是慢。
修改模板
liuxiaoyan@development:~/mysite/templates$ cat search_results.html <p>You searched for: <strong>{{ query }}</strong></p> {% if books %} <p>Found {{ books|length }} book{{ books|pluralize }}.</p> <ul> {% for book in books %} <li>{{ book.title }}</li> {% endfor %} </ul> {% else %} <p>No books matched your search criteria.</p> {% endif %}
這裏pluralize過濾器在適當的時候輸出s(即books)。
結果:
如今搜索表單對空字符串的處理至關薄弱,僅顯示一條"Please submit a search term"提示信息,以下圖,若用戶要從新填寫表單必須自行點擊「後退」按鈕,這種作法糟糕又不專業。
在檢查到空字符串時更好的解決方法是從新顯示錶單,並在表單上面給出錯誤提示以便用戶馬上從新填寫。最簡單的方法就是添加else分句從新顯示錶單。
視圖
liuxiaoyan@development:~/mysite/books$ cat views.py
# Create your views here. from django.shortcuts import render_to_response from django.http import HttpResponse from books.models import Book def search_form(request): return render_to_response('search_form.html') def search(request): if 'q' in request.GET and request.GET['q']: q = request.GET['q'] books = Book.objects.filter(title__icontains=q) return render_to_response('search_results.html', {'books': books, 'query': q}) else: # return HttpResponse('Please submit a search term.')
#字符串爲空時,給search_form.html傳遞一個變量error,並從新顯示
return render_to_response('search_form.html',{'error':True})
模板:須要檢測error變量,調用search_form視圖時,沒有error變量,因此不會顯示錯誤信息。
liuxiaoyan@development:~/mysite/templates$ cat search_form.html <html> <head> <title>Search</title> </head> <body> {% if error %} <p style="color: red;">Please submit a search term.</p> {% endif %} <form action="/search/" method="get"> <input type="text" name="q"> <input type="submit" value="Search"> </form> </body> </html>
如今
沒有必要專門編寫search_form()來顯示錶單!!
修改視圖:
liuxiaoyan@development:~/mysite/books$ cat views.py # Create your views here. from django.shortcuts import render_to_response from django.http import HttpResponse from books.models import Book def search(request): error=False if 'q' in request.GET: q = request.GET['q'] if not q: error=True 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',{'error':error})
若是用戶訪問/search/而且沒有帶GET數據,那麼他將看到一個沒有錯誤信息的表單。(由於error=False,'q' in request.GET爲假,直接執行最後一行跳轉到search_form.html,且error爲假,不顯示提示信息);
若是用戶提交了一個空表單,他將看到錯誤提示信息,還有表單;(由於if not q爲真,error被置爲真,執行最後一行跳轉到search_form.html,提示出錯i型哪些);
若是用戶提交了一個非空值,他將看到出錯結果。
模板:去掉冗餘代碼
liuxiaoyan@development:~/mysite/templates$ cat search_form.html <html> <head> <title>Search</title> </head> <body> {% if error %} <p style="color: red;">Please submit a search term.</p> {% endif %} <form action="" method="get"> <input type="text" name="q"> <input type="submit" value="Search"> </form> </body> </html>
Note:
表單中action="/search/"改成search="",action=""意味着表單將提交給與當前頁面相同的URL。
在客戶端可用JavaScript對數據進行驗證,同時在服務器端必須再驗證一次,由於有些傢伙可能關閉javascript對服務器攻擊。如下介紹的是服務器端的驗證。
改進search()視圖,讓它驗證搜索關鍵字是否小於或者等於20個字符。
修改視圖
最簡單的方式就是將邏輯嵌入到視圖。要注意一點處理多種出錯信息,因此再也不使用布爾類型,而用列表來記錄出錯信息。
liuxiaoyan@development:~/mysite/books$ cat views.py # Create your views here. from django.shortcuts import render_to_response from django.http import HttpResponse from books.models import Book 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})
修改模板:
liuxiaoyan@development:~/mysite/templates$ cat search_form.html <html> <head> <title>Search</title> </head> <body> {% if errors %} <ul> {% for error in errors %} <li style="color:red">{{ error }}</li> {% endfor %} </ul> {% endif %} <form action="" method="get"> <input type="text" name="q"> <input type="submit" value="Search"> </form> </body> </html>
視圖根據不一樣查找信息返回不一樣錯誤或者結果:
如下開始一個新的例子——站點聯繫表單,而且涉及服務器端的操做,因此使用POST,記住一點,咱們應該每次都給成功的POST請求作重定向。
由於站點聯繫表單跟books模型沒有半毛錢關係,因此咱們新建一個contact 的APP。
liuxiaoyan@development:~/mysite$ python manage.py startapp contact
表單功能:用戶反饋,即表單包括用戶提交的反饋信息,一個可選的e-mail回信地址,當這個表單提交而且數據經過驗證後,系統將自動發送一封包含用戶提交信息的e-mail給站點工做人員。【//lxy:其實就是根據用戶提交信息發郵件,郵箱要本身給定】
由於涉及到發郵件,先說一下settings.py郵件相關配置
配置:
首先在MIDDLEWARE_CLASSES中註釋掉'django.middleware.csrf.CsrfViewMiddleware'。
而後配置好郵件代理服務器
#send email EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST='smtp.126.com' #SMTP服務器 EMAIL_PORT = 25 #SMTP端口 EMAIL_HOST_USER = 'starof@126.com' #用該郵箱發郵件,郵箱必須有效 EMAIL_HOST_PASSWORD = '******' #郵箱密碼,必須正確
EMAIL_USE_TLS = True #與SMTP服務器通訊時,是否啓動TLS鏈接(安全鏈接),默認爲false
配置好後能夠先用一個小demo測試一下:
liuxiaoyan@development:~/mysite$ cat testSendEmail.py from django.core.mail import send_mail from django.http import HttpResponse def sendEmail(request): send_mail('subject', 'this is the message of email', 'starof@126.com', ['reseive@example.com'], fail_silently=True) return HttpResponse('successful')
url配置
from testSendEmail import * urlpatterns = patterns('', ... (r'^mail/$',sendEmail), ... )
如今測試咱們發郵件成功,說明配置正確,接下來回到contact。先看contact_form.html
liuxiaoyan@development:~/mysite/templates$ cat contact_form.html
<html>
<head>
<title>Contact us</title>
</head>
<body>
<h1>Contact us</h1> {% if errors %} <ul> {% for error in errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} <form action="" method="post"> {% csrf_token %} <p>Subject:<input type="text" name="subject"></p> <p>Your e-mail (optional):<input type="text" name="email"></p> <p>Message:<textarea name="message" row="10" cols="50"></textarea></p> <input type="submit" value="Submit"> </form> </body> </html>
在視圖中加入
from django.core.mail import send_mail
liuxiaoyan@development:~/mysite/contact$ cat views.py # Create your views here. from django.core.mail import send_mail from django.http import HttpResponseRedirect from django.shortcuts import render_to_response from django.template import RequestContext 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']: #弱弱的驗證一下email errors.append('Enter a valid e-mail address.') if not errors: send_mail( #包括主題,正文,寄信人,收信人列表 request.POST['subject'], #request.POST獲取提交過來的數據 request.POST['message'], #request.POST.get('email', 'starof@126.com'), 'starof@126.com', #settings.py中配置的發郵件的郵箱 ['925xxxx23@qq.com','xxx@xxx.com'], #收郵件的郵箱,可配置多個 fail_silently=True ) return HttpResponseRedirect('/contact/thanks/') #郵件發送成功重定向頁面 return render_to_response('contact_form.html',{'errors': errors},context_instance=RequestContext(request)) #return render_to_response('contact_form.html',{'errors': errors}) def thank(request): return render_to_response('thank.html')
郵件發送成功爲何用HttpResponseRedirect重定向而不用render_to_response輸出?
若是用戶刷新一個包含POST表單的頁面,那麼請求將從新發送形成重複。會形成非指望的結果,好比重複的數據庫記錄,在本例將致使發送兩封一樣的郵件。若是用戶在POST表單以後重定向至另外的頁面,就不會形成重複的請求了。每次都應該給成功的POST作重定向,這是web開發的最佳實踐。
郵件發送後會跳轉到/contact/thanks/的url,
urls.py配置以下:
(r'^contact/$',contact), (r'^contact/thanks/$', thank),
因此再添加一個發郵件成功thank.html模板
liuxiaoyan@development:~/mysite/templates$ cat thank.html
<html>
<body>
<h2>thank you very much!!!</h2>
</body>
</html>
爲了有更好的用戶體驗,讓數據驗證失敗後,返回客戶端的表單中各字段最好是填有原來提交的數據,以便用戶查看哪裏出現錯誤(用戶也不須要再次填寫正確的字段值)。手動將原來的提交數據返回給模板。
liuxiaoyan@development:~/mysite/contact$ cat views.py # Create your views here. from django.core.mail import send_mail from django.http import HttpResponseRedirect from django.shortcuts import render_to_response from django.template import RequestContext 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', 'starof@126.com'), 'starof@126.com', ['xxx@xxx.com','9xxxx3@qq.com'], fail_silently=True ) return HttpResponseRedirect('/contact/thanks/') return render_to_response('contact_form.html',{'errors': errors,'subject':request.POST.get("subject",''),'message':request.POST.get('message',''),'email':request.POST.get('email',''),},context_instance=RequestContext(request)) #return render_to_response('contact_form.html',{'errors': errors}) def thank(request): return render_to_response('thank.html')
解決辦法:
第一步,在template中,爲每一個POSTform增長一個{% csrf_token %}標籤。以下:
<form> {% csrf_token %} ... </form>
第二步,在view中,使用django.template.RequestContext而不是Context。render_to_response,默認使用Context,須要改爲RequestContext。RequestContext會處理csrf_token這個tag,自動爲表單添加一個名爲csrfmiddlewaretoken的input。
具體作法以下:
導入class
from django.template import RequestContext
給render_to_response增長一個參數:
def your_view(request): ... return render_to_response('template.html', your_data, context_instance=RequestContext(request) )
原理:
Django自帶一個form庫,用作HTML表單顯示以及驗證。就是不用本身寫頁面的form表單,寫個Form類再加一堆使用Form的代碼django 本身給你一個活生生的表單,還能幫你驗證。【//lxy:可能單純的後臺程序員會喜歡這樣用,若是習慣寫頁面的人,更傾向於本身寫個fashion的表單本身加js驗證吧,可是存在即合理,看看這個傳說中的djangoForm表單框架吧。此爲我的觀點】
爲每個將要處理的HTML"<Form>" 定義一個Form類,慣例是把Form類都放在一個文件中:forms.py。
liuxiaoyan@development:~/mysite/contact$ cat forms.py from django import forms class ContactForm(forms.Form): subject=forms.CharField() email=forms.EmailField(required=False) message=forms.CharField()
表單的每一個字段(域)做爲Form類的屬性,被展示爲Field類。字段默認都是必填的,要讓email可選,特別指定reqired=False。
如今到關鍵時刻了,看看Form框架幕後的工做:
liuxiaoyan@development:~/mysite$ python manage.py shell Python 2.7.3 (default, Feb 27 2014, 19:58:35) [GCC 4.6.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> 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_subject" /></td></tr> <tr><th><label for="id_email">Email:</label></th><td><input type="text" name="email" id="id_email" /></td></tr> <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr> >>>
能夠看到Djagno默認用<table>格式輸出表單。
若是用列表ul格式:
>>> print f.as_ul() <li><label for="id_subject">Subject:</label> <input type="text" name="subject" id="id_subject" /></li> <li><label for="id_email">Email:</label> <input type="text" name="email" id="id_email" /></li> <li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li> >>>
若是用段落p格式:
>>> print f.as_p() <p><label for="id_subject">Subject:</label> <input type="text" name="subject" id="id_subject" /></p> <p><label for="id_email">Email:</label> <input type="text" name="email" id="id_email" /></p> <p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p> >>>
快捷顯示
>>> print f['subject'] <input type="text" name="subject" id="id_subject" /> >>> print f['message'] <input type="text" name="message" id="id_message" /> >>>
建立一個新的Form對象,並傳入數據。
liuxiaoyan@development:~/mysite$ python manage.py shell Python 2.7.3 (default, Feb 27 2014, 19:58:35) [GCC 4.6.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> from contact.forms import ContactForm >>> f = ContactForm({'subject': 'Hello', 'email': 'adrian@example.com', 'message': 'Nice site!'}) >>>
給一個Form實體賦值後,就獲得了一個綁定的form,以後在視圖中也會這麼用。
>>> f.is_bound
True
調用任何已綁定form的is_valid()方法,就能夠指定它的數據是否合法。
如今什麼值都給了,固然是合法的了。
>>> f.is_valid()
True
若是不給subject或message賦值,整個Form就再也不合法了。
>>> f = ContactForm({'subject': 'Hello'}) >>> f.is_valid() False >>> f = ContactForm({'subject': 'Hello', 'message': ''}) >>> f.is_valid() False >>>
接下來看看錯誤消息,可經過每一個字段來看,也可直接經過Form實體來看。
逐一查看字段的出錯消息:
>>> f = ContactForm({'subject': 'Hello', 'message': ''}) >>> f['message'].errors [u'This field is required.'] >>> f['subject'].errors [] >>> f['email'].errors [] >>>
由於每一個綁定的Form實體都有一個errors屬性,提供一個字段與出錯消息相映射的字典表。以後的模板中會用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': 'adrian@example.com', 'message': 'Nice site!'}) >>> f.is_valid() True >>> f.cleaned_data {'message': u'Nice site!', 'email': u'adrian@example.com', 'subject': u'Hello'} >>>
若是數據不合法會報錯:
>>> f = ContactForm({'subject': 'Hello', 'message': ''}) >>> f.is_valid() False >>> f.cleaned_data Traceback (most recent call last): File "<console>", line 1, in <module> AttributeError: 'ContactForm' object has no attribute 'cleaned_data' >>>
djangoForm框架頁沒什麼神祕的,使用它將contact視圖改版,確實會輕便很多,若是表單的數據不少的時候其優點就體現的更明顯。視圖代碼:
liuxiaoyan@development:~/mysite/contact$ cat views.py # Create your views here. from django.core.mail import send_mail from django.http import HttpResponseRedirect from django.shortcuts import render_to_response from django.template import RequestContext from forms import ContactForm #導入ContactForm表單類 def contact(request): errors = [] 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','starof@126.com'), 'starof@126.com', ['liuxiaoyan@windawn.com'], fail_silently=True ) return HttpResponseRedirect('/contact/thanks/') else: form=ContactForm() return render_to_response('contact_form.html',{'form':form}, context_instance=RequestContext(request)) def thank(request): return render_to_response('thank.html')
模板也要稍作處理:
liuxiaoyan@development:~/mysite/templates$ cat 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="/contact/" method="post"> {% csrf_token %} <table> {{form.as_table}} </table> <input type="submit" value="Submit"> </form> </body> </html>
Django的forms框架處理HTML顯示、數據校驗、數據清理和表單錯誤重現。
看看效果,【//lxy:不得不感嘆真是個醜陋的表單!!!】
驗證效果以下:
發郵件徹底正確:
以上看到form框架原生的表單是否是醜到沒朋友了。
message字段被顯示成"input type="text"",而它應該被顯示成<"textarea">。
liuxiaoyan@development:~/mysite/contact$ cat forms.py 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類表現「校驗邏輯」,部件表現"顯示邏輯"。
liuxiaoyan@development:~/mysite/contact$ cat forms.py 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)
限制subject在100個字符之內。即爲CharField提供max_length參數。超過100個字符就無法輸入了,測試時可將100改成3來試一下。
爲字段subject添加初始值"I love your site!"。經過在建立Form實體時,使用initial參數。
liuxiaoyan@development:~/mysite/contact$ cat views.py # Create your views here. from django.core.mail import send_mail from django.http import HttpResponseRedirect from django.shortcuts import render_to_response from django.template import RequestContext from forms import ContactForm def contact(request): errors = [] 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','starof@126.com'), 'starof@126.com', ['liuxiaoyan@windawn.com'], fail_silently=True ) return HttpResponseRedirect('/contact/thanks/') else: form=ContactForm( initial={'subject':'I love your site!'} #初始設置主題爲I love your site! ) return render_to_response('contact_form.html',{'form':form}, context_instance=RequestContext(request)) def thank(request): return render_to_response('thank.html')
僅傳入初始值的表單是未綁定狀態的。
大多數自定義校驗都是一次性的,能夠直接綁定到form。給"message"字段額外的校驗,至少有4個單詞。
liuxiaoyan@development:~/mysite/contact$ cat forms.py 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,at least 4 words!") return message
Django的form系統自動尋找以clean_開頭並以字段名稱結束的方法。若是有這樣的方法,它將在默認校驗的以後被調用。
Note:
在函數的末尾顯示返回字段很是重要。若是忘記,原始數據就丟了。即form.cleaned_data['message] 這個值就爲None,若是在模板用到這個值就哭去吧。
Form表單標籤生成規則爲:空格代替下劃線,首字母大寫。如email的標籤是"Email"(一樣的邏輯被用於模型(model)中字段的verbose_name值)。如今將email自定義爲"Your e-mail address"。
liuxiaoyan@development:~/mysite/contact$ cat forms.py from django import forms 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) def clean_message(self): message=self.cleaned_data['message'] num_words=len(message.split()) if num_words<4: raise forms.ValidationError("Not enough words,at least 4 words!") return message
以前在模板中使用{{form.as_table}}顯示錶單,這樣自動生成在開發時快捷方便,可是生產環境,可能想要覆蓋默認的顯示,因此就要重寫。
每個字段部件(<input type="text">,<select>,<textarea>等)都e抗原經過訪問{{form.字段名}}進行單獨渲染。這裏將主動權交到咱們手中了。
liuxiaoyan@development:~/mysite/templates$ cat 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"> {% csrf_token %} <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沒有被綁定就顯示一個空字符串。【//lxy:該ul是默認的】
能夠給它加上css樣式,讓li顯示更突出。
liuxiaoyan@development:~/mysite/templates$ cat contact_form.html <html> <head> <title>Contact us</title> <style type="text/css"> .field{ bakcground-color:blue; } ul{ margin: 0; padding: 0; } .errorlist li { background-color: red; color: white; display: block; font-size: 10px; margin: 0 0 3px; padding: 4px 5px; } </style> </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"> {% csrf_token %} <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當作一個布爾值或者當它是list在上面作迭代。【//lxy:只是說能夠這麼用,但你不必定要這麼用】
liuxiaoyan@development:~/mysite/templates$ cat contact_form.html <html> <head> <title>Contact us</title> <style type="text/css"> .field{ bakcground-color:blue; } ul{ margin: 0; padding: 0; } .errorlist li { background-color: red; color: white; display: block; font-size: 10px; margin: 0 0 3px; padding: 4px 5px; } </style> </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"> {% csrf_token %} <div class="field {% if form.subject.errors %}errorlist{% endif %}"> {% if form.message.errors %} <ul> {% for error in form.subject.errors %} <li><strong>{{ error }}</strong></li> {% endfor %} </ul> {% endif %} <label for="id_subject">Subject:</label> {{ form.subject }} </div> <div class="field {% if form.email.errors %}errorlist{% endif %}"> {% if form.message.errors %} <ul> {% for error in form.email.errors %} <li><strong>{{ error }}</strong></li> {% endfor %} </ul> {% endif %} <label for="id_email">Your e-mail address:</label> {{ form.email }} </div> <div class="field {% if form.message.errors %}errorlist{% 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> {{ form.message }} </div> <input type="submit" value="Submit"> </form> </body> </html>
效果和最後一張圖同樣。
資源連接: