现在的位置: 首页 > 综合 > 正文

认识django2.0读书笔记(7)—第七章 表单

2013年04月15日 ⁄ 综合 ⁄ 共 17860字 ⁄ 字号 评论关闭
文章目录

文档下载地址: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:

MAIL

/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)

  1. HTML里我们定义了一个变量q。当提交表单时,变量q的值通过GET(method=”get”)附加在URL /search/上。注意q是在html中自定义的,并不是默认的或者没有根据得来的。
  1. 处理/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):

   **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** })

修改search_form.html文件

 

<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

 

class ContactForm(forms.Form):

   subject = forms.CharField(**max_length=100** )#这样显示时使subject限制在100字符内

   email = forms.EmailField(required=False)

   message = forms.CharField(widget=forms.Textarea)

类似的还有min_length

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应用程序(第十二章)。

抱歉!评论已关闭.