文档下载地址:Django_2.0_中文教程 http://download.csdn.net/detail/julius_lee/6620099
在线地址:http://djangobook.py3k.cn/2.0/
Django 2.0 Book 关键内容记录,主要是为了帮助记忆和理清整个框架,同时以后忘了可以查看,回想。
介绍django对用户通过表单的提交进行的数据访问,有效性检查,及其处理
1、 request对象获取数据
示例:view视图函数
from django.http import HttpResponse
def hello(request):
return HttpResponse("Hello world")
HttpRequest对象包含当前请求URL的一些信息:
属性/方法 |
说明 |
举例 |
request.path |
除域名以外的请求路径,以正斜杠开头 |
"/hello/" |
request.get_host() |
主机名(比如,通常所说的域名) |
"127.0.0.1:8000" or "www.example.com" |
request.get_full_path() |
请求路径,可能包含查询字符串 |
"/hello/?print=true" |
request.is_secure() |
如果通过HTTPS访问,则此方法返回True, 否则返回False |
True 或者 False2 |
在view函数里,要始终用这个属性或方法来得到URL,而不要手动输入。 这会使得代码更加灵活,以便在其它地方重用。下面是一个简单的例子:
# BAD!这样,当收到请求后,直接转为请求的路径,以后修改都不用再改视图函数了。
def current_url_view_bad(request):
return HttpResponse("Welcome to the page at /current/")
# GOOD
def current_url_view_good(request):
return HttpResponse("Welcome to the page at %s" %request.path)
关于request.META
request.META是一个字典,包含http请求的Header信息,内容如下:
代码:
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))
CONTENT_LENGTH |
|
CONTENT_TYPE |
text/plain |
CSRF_COOKIE |
vslS1e5VacqktmIG0ZnQMX5KJ1T7XxLV |
DJANGO_SETTINGS_MODULE |
mysite.settings |
GATEWAY_INTERFACE |
CGI/1.1 |
HOME |
/home/loongson |
HTTP_ACCEPT |
text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 |
HTTP_ACCEPT_ENCODING |
gzip, deflate |
HTTP_ACCEPT_LANGUAGE |
zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3 |
HTTP_CONNECTION |
keep-alive |
HTTP_COOKIE |
bdshare_firstime=1361237552004; csrftoken=vslS1e5VacqktmIG0ZnQMX5KJ1T7XxLV; sessionid=smdblfqnq9kio5syti5vmqgdo8pqek7r |
HTTP_DNT |
1 |
HTTP_HOST |
172.16.3.62:8080 |
HTTP_USER_AGENT |
Mozilla/5.0 (Windows NT 6.1; rv:25.0) Gecko/20100101 Firefox/25.0 |
LANG |
zh_CN.UTF-8 |
LANGUAGE |
zh_CN:zh |
LOGNAME |
loongson |
LS_COLORS |
rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36: |
/var/mail/loongson |
|
OLDPWD |
/home/loongson |
PATH |
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games |
PATH_INFO |
/values/ |
PWD |
/home/loongson/python/django/second_poll |
QUERY_STRING |
|
REMOTE_ADDR |
172.16.7.94 |
REMOTE_HOST |
|
REQUEST_METHOD |
GET |
RUN_MAIN |
true |
SCRIPT_NAME |
|
SERVER_NAME |
LOonux-3.local |
SERVER_PORT |
8080 |
SERVER_PROTOCOL |
HTTP/1.1 |
SERVER_SOFTWARE |
WSGIServer/0.1 Python/2.6.6 |
SHELL |
/bin/bash |
SHLVL |
1 |
SSH_CLIENT |
172.16.7.94 65295 22 |
SSH_CONNECTION |
172.16.7.94 65295 172.16.3.62 22 |
SSH_TTY |
/dev/pts/1 |
TERM |
xterm |
TZ |
Asia/Shanghai |
USER |
loongson |
XDG_RUNTIME_DIR |
/run/user/loongson |
XDG_SESSION_COOKIE |
51a0886c4aebc7a8473cc3a2000008c4-1385514067.991625-1414976123 |
XDG_SESSION_ID |
194c |
_ |
/usr/bin/python |
wsgi.errors |
|
wsgi.file_wrapper |
wsgiref.util.FileWrapper |
wsgi.input |
|
wsgi.multiprocess |
False |
wsgi.multithread |
True |
wsgi.run_once |
False |
wsgi.url_scheme |
http |
wsgi.version |
(1, 0) |
注意:
因为request.META 是一个普通的Python字典,因此当试图访问一个不存在的键时,会触发一个KeyError异常。 (HTTP header信息是由用户的浏览器所提交的、不应该给予信任的“额外”数据,因此应该好好设计你的应用以便当一个特定的Header数据不存在时,给出一个优雅的回应。)用 try/except 语句,或者用Python字典的 get() 方法来处理这些“可能不存在的键”:
示例:
# BAD!
def ua_display_bad(request):
ua = request.META['HTTP_USER_AGENT'] # Might raise KeyError!
return HttpResponse("Your browser is %s" % ua)
# GOOD (VERSION 1)
def ua_display_good1(request):
try:
ua = request.META['HTTP_USER_AGENT']
except KeyError:
ua = 'unknown'
return HttpResponse("Your browser is %s" % ua)
# GOOD (VERSION 2)
def ua_display_good2(request):
ua = request.META.get('HTTP_USER_AGENT', 'unknown')
return HttpResponse("Your browser is %s" % ua)
使用try或者get避免header数据不存在引发的异常。
2、 提交数据信息
HttpRequest 还包含用户提交的信息:request.GET和request.POST,为类字典对象。
request.GET和request.POST都有get()、keys()和values()方法,你可以用用 for key in request.GET 获取所有的键。
POST数据是来自HTML中的〈form〉标签提交的,而GET数据可能来自〈form〉提交也可能是URL中的查询字符串(the query string)。
3、 表单处理示例
表单开发分为:前端HTML页面接口,后台view函数对提交数据处理过程
1) 创建搜索表单
示例:books目录下创建views.py
from django.shortcuts importrender_to_response
def search_form(request):
return render_to_response('search_form.html')
再在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>
最后添加URLpattern到urls.py中
from mysite.books import views
urlpatterns = patterns('',
#...
(r'^search-form/$', views.search_form),
#...
)
这样就可以出现一个搜索框在页面左上角了;也就是修改三个地方,view函数,url地址和html文件。Html文件需要了解其语法,才好书写。
但提交数据会报错404,因为form指向的search还没有实现;
需要添加第二个视图,并设置url如下:
# urls.py
urlpatterns = patterns('',
#...
(r'^search-form/$', views.search_form),#注意变量的写法,文件名.函数名
(r'^search/$', views.search),
#...
)
# views.py
def search(request):
if 'q' in request.GET:
message = 'You searched for: %r' % request.GET['q']#q源于html文档的name定义
else:
message = 'You submitted an empty form.'
return HttpResponse(message)
- 在HTML里我们定义了一个变量q。当提交表单时,变量q的值通过GET(method=”get”)附加在URL /search/上。注意q是在html中自定义的,并不是默认的或者没有根据得来的。
- 处理/search/(search())的视图通过request.GET来获取q的值。
需要注意的是在这里明确地判断q是否包含在request.GET中。就像上面request.META小节里面提到,对于用户提交过来的数据,甚至是正确的数据,都需要进行过滤。 在这里若没有进行检测,那么用户提交一个空的表单将引发KeyError异常
确认数据有效后,下一步将从数据库查询数据。
from django.http import HttpResponse作用:
from django.shortcuts importrender_to_response
from mysite.books.models import Book
def search(request):
if 'q' in request.GET and request.GET['q']:
q = request.GET['q']
books = Book.objects.filter(title__icontains=q)#使用icontains查询,赋值给html中的books
return render_to_response('search_results.html',
{'books': books, 'query': q})#返回字典查询结果,query是查询的q 变量
else:
return HttpResponse('Please submit a search term.')
除了检查q是否存在于request.GET之外,我们还检查来reuqest.GET[‘q’]的值是否为空;
使用Book.objects.filter(title__icontains=q)获取数据库中标题包含q的书籍;
给模板传递来books,一个包含Book对象的列表;
查询结果的显示模板search_results.html如下:
<p>You Searched for :<strong>{{query }}</strong></p>
{% if books %}#books也就是q值,源于render_to_response
<p>Found {{ books|length }} book{{ books|pluralize }}.</p>#pluralize这个过滤器在适当的时候会输出s(例如找到多本书籍)
<ul>
{% for book in books %}
<li>{{ book.title }}</li>
{% endfor %}
</ul>
{% else %}
<p>NO books matched your search criteria.</P>
{% endif %}
~
结果:
找到:
YouSearched for :Nono
Found 1 book.
Nono
没有找到:
YouSearched for :Nono334
NO books matched your search criteria.
其界面如下图所示:
4、 改进表单
首先,search()视图对于空字符串的处理相当薄弱——仅显示一条”Please submit a search term.”的提示信息。 若用户要重新填写表单必须自行点击“后退”按钮, 这种做法既糟糕又不专业。
在检测到空字符串时更好的解决方法是重新显示表单,并在表单上面给出错误提示以便用户立刻重新填写。最简单的实现方法既是添加else分句重新显示表单,代码如下:
from django.http import HttpResponse
from django.shortcuts importrender_to_response
from mysite.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 render_to_response('search_form.html', {'error': True})**#字符串为空时重新显示search_form.html
改进search()视图:在字符串为空时重新显示search_form.html。 并且给这个模板传递了一个变量error,记录错误提示信息。 现在我们编辑一下search_form.html,检测变量error,如下:
<html>
<head>
<title>Search</title>
</head>
<body>
**{% if error %}**#如果有错,则显示下列信息
**<p style="color: red;">Please submit a searchterm.</p>**
**{% endif %}**
<form action="/search/" method="get">
<input type="text" name="q">
<input type="submit" value="Search">
</form>
</body>
</html>
但是现在出现一个问题: 是否有必要专门编写search_form()来显示表单? 按实际情况来说,当一个请求发送至/search/(未包含GET的数据)后将会显示一个空的表单(带有错误信息)。 所以,需要改变search()视图:当用户访问/search/并未提交任何数据时就隐藏错误信息,这样就移去search_form()视图以及 对应的URLpattern。
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数据。则报错
在改进后的视图中,若用户访问/search/并且没有带有GET数据,那么他将看到一个没有错误信息的表单; 如果用户提交了一个空表单,那么它将看到错误提示信息,还有表单;最后,若用户提交了一个非空的值,那么他将看到搜索结果。
既然已经将两个视图与URLs合并起来,/search/视图管理着表单的显示以及结果的显示,那么在search_form.html里表单的action值就没有必要硬编码的指定URL。 原先的代码是这样:
<form action="/search/"method="get">
现在改成这样:
<form action=""method="get">
action=”“意味着表单将提交给与当前页面相同的URL。
5、 简单的验证
主要是针对目前的数据验证太过简单,实际中会遇到特定格式的验证,如邮件地址,邮编,日期等。
解决办法:
Javascript验证
服务器端验证
示例:
修改view函数
def search(request):修改search_form.html文件
**errors = []**
if'q' in request.GET:
q = request.GET['q']
if not q:
**errors.append('Enter a search term.')**#利用append给出对应出错提示
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** })
<html>
<head>
<title>Search</title>
</head>
<body>
**{% if errors %}**
**<ul>**
**{% for error in errors %}**#显示一个errors列表
**<li>{{ error }}</li>**
**{% endfor %}**
**</ul>**
**{% endif %}**
<form action="/search/" method="get">
<input type="text"name="q">
<input type="submit" value="Search">
</form>
</body>
</html>
6、 编写contact表单
示例:联系站点的表单
表单内容:用户反馈信息,email回信地址;表单提交验证后,系统自动发送email给站点人员
准备:新建一个contact文件夹在project下面,与books同级,建立空文件__init__.py
1)编写contact_form.html,定义主题,email和反馈信息
<html>
<head>
<title>Contactus</title>
</head>
<body>
<h1>Contactus</h1>
{% if errors %}#如果有错,则显示错误信息
<ul>
{% for error inerrors %}
<li>{{ error}}</li>
{% endfor %}
</ul>
{% endif %}
<formaction="/contact/" method="post">#method="post"会进行服务器端操作,发送email
<p>Subject:<input type="text" name="subject"></p>#标题
<p>Your e-mail(optional): <input type="text"name="email"></p>
<p>Message:<textarea name="message" rows="10"cols="50"></textarea></p>
<inputtype="submit" value="Submit">
</form>
</body>
</html>
2) 编写contact视图,
from django.core.mail import send_mail
from django.http import HttpResponseRedirect
from django.shortcuts importrender_to_response
def contact(request):
errors = []
if request.method == 'POST':#<!--使用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','noreply@example.com'),
['siteowner@example.com'],
)
return HttpResponseRedirect('/contact/thanks/')
return render_to_response('contact_form.html',
{'errors': errors})
说明:
使用request.POST代替request.GET来获取提交过来的数据。 这是必须的,因为contact_form.html里表单使用的是method=”post”。如果在视图里通过POST获取数据,那么request.GET将为空。
有两个必填项,subject和 message,所以需要对这两个进行验证。注意,使用request.POST.get()方法,并提供一个空的字符串作为默认值;这个方法很好的解决了键丢失与空数据问题。
虽然email非必填项,但如果有提交的值则也需进行验证。验证算法相当的薄弱,仅验证值是否包含@字符。 在实际应用中,需要更为健壮的验证机制(Django提供这些验证机制)。
使用了django.core.mail.send_mail函数来发送e-mail。 这个函数有四个必选参数: 主题,正文,寄信人和收件人列表。 send_mail是Django的EmailMessage类的一个方便的包装,EmailMessage类提供了更高级的方法,比如附件,多部分邮 件,以及对于邮件头部的完整控制。
当邮件发送成功之后,使用HttpResponseRedirect对象将网页重定向至一个包含成功信息的页面。但是要解释一下为何重定向至新的页面,而不是在模板中直接调用render_to_response()来输出:原因就是: 若用户刷新一个包含POST表单的页面,那么请求将会重新发送造成重复。 这通常会造成非期望的结果,比如说重复的数据库记录;在例子中,将导致发送两封同样的邮件。
应每次都给成功的POST请求做重定向。 这就是web开发的最佳实践。
3) 表单的重新显示
数据验证失败后返回表单中原来提交的数据,就不用再填写一次正确的数据了。通过手动将原来提交的数据返回给模板,编辑html里的各字段填充原来的值
示例:
# views.py
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',`'noreply@example.com`_'),
[`'siteowner@example.com`_'],
)
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', ''),**
})
# 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="/contact/"method="post"> <!--增加value值--> <p>Subject: <input type="text" name="subject" **value="{{ subject}}"** ></p> <p>Your e-mail (optional):<input type="text" name="email" **value="{{ email}}"** ></p> <p>Message: <textarea name="message" rows="10" cols="50">**{{message }}**</textarea></p> <input type="submit"value="Submit"> </form></body></html>
7、 第一个form类
Django.forms库,处理html表单显示及验证
在存放views.py的目录中创建form.py文件
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField()#使用charField类型
email = forms.EmailField(required=False)#emailFild类型,false表示email是可选项
message = forms.CharField()
实际上,这个类就是将对应的subject,email等内容格式化成为html内容,添加标签等
示例:
>>> from contact.forms importContactForm
>>> f = ContactForm()
>>> print f
<tr><th><labelfor="id_subject">Subject:</label></th><td><inputtype="text" name="subject" id="id_subject"/></td></tr>
<tr><th><labelfor="id_email">Email:</label></th><td><inputtype="text" name="email" id="id_email"/></td></tr>
<tr><th><labelfor="id_message">Message:</label></th><td><inputtype="text" name="message" id="id_message"/></td></t
其次,进行数据的校验
>>> f = ContactForm({'subject':'Hello', 'email': 'adrian@example.com', 'message': 'Nice site!'})
>>> f.is_bound
True
例如以上创建了一个新的Form对象,并且传入一个与定义匹配的字典类型数据,对一个Form实体赋值,得到了一个绑定form,调用任何绑定form的is_valid()方法,就可以知道它的数据是否合法
>>> f.is_valid()
True
1)视图中使用form对象
示例:使用forms框架重写contact
# views.py
from django.shortcuts importrender_to_response
from mysite.contact.forms importContactForm
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>
2)改变字段显示
在本地显示这个表单的时,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)中
4) 设置最大长度
经常使用的校验要求是检查字段长度。
from django import forms类似的还有min_length
class ContactForm(forms.Form):
subject = forms.CharField(**max_length=100** )#这样显示时使subject限制在100字符内
email = forms.EmailField(required=False)
message = forms.CharField(widget=forms.Textarea)
5) 设置初始值
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!'}**#为subject字段添加初始值
)
return render_to_response('contact_form.html', {'form': form})
注意,传入* 初始值* 数据和传入数据以* 绑定* 表单是有区别的。 最大的区别是,如果仅传入* 初始值* 数据,表单是unbound的,那意味着它没有错误消息。
6) 自定义校验规则
示例:对提交的消息规定必须大于4个字符,并创建自定义校验字段类型,希望`` message`` 字段有一个额外的校验,我们增加一个`` clean_message()`` 方法到`` Form`` 类:clean_message()方法将在指定字段的默认校验逻辑执行* 之后* 被调用。因为字段数据已经被部分处理,所以它被从self.cleaned_data中提取出来了;
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
简单地使用了len()和split()的组合来计算单词的数量。 如果用户输入字数不足,我们抛出一个forms.ValidationError型异常。这个异常的描述会被作为错误列表中的一项显示给用户。
在函数的末尾显式地返回字段
7) 指定标签
需使用label,像这样:
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
email = forms.EmailField(required=False, **label='Your e-mail address'**)#label自定义标签
message = forms.CharField(widget=forms.Textarea)
8)定制form设计
在上面`` contact_form.html``模板中我们使用``{{form.as_table}}`` 显示表单,不过可以使用其他更精确控制表单显示的方法,示例:
<style type="text/css">
ul.errorlist {
margin: 0;
padding: 0;
}
.errorlist li {
background-color: red;
color: white;
display: block;
font-size: 10px;
margin: 0 0 3px;
padding: 4px 5px;
}
</style>
修改form的显示的最快捷的方式是使用CSS。自动生成的错误列表精确的使用`` <ulclass=”errorlist”>``
每一个字段部件(<inputtype=”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{% ifform.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>
{{ form.message }}
</div>
在校验失败的情况下, 这段代码会在包含错误字段的div的class属性中增加一个”errors”,在一个有序列表中显示错误信息。
这一章总结了本书的“核心教程”。
前七章介绍的内容就到此结束,后续再补充一些练习,巩固后再继续后续章节;
后面部分,从第八章到第十二章,将详细讲述高级(进阶)使用,包括如何配置一个Django应用程序(第十二章)。