表单是交互性网站的支柱。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>
效果和最后一张图同样。
资源连接: