详解Django中的form库的使用
Django带有一个form库,称为django.forms,这个库可以处理我们本章所提到的包括HTML表单显示以及验证。接下来我们来深入了解一下form库,并使用她来重写contact表单应用。
Django的newforms库
在Django社区上会经常看到django.newforms这个词语。当人们讨论django.newforms,其实就是我们本章里面介绍的django.forms。
改名其实有历史原因的。当Django一次向公众发行时,它有一个复杂难懂的表单系统:django.forms。后来它被完全重写了,新的版本改叫作:django.newforms,这样人们还可以通过名称,使用旧版本。当Django1.0发布时,旧版本django.forms就不再使用了,而django.newforms也终于可以名正言顺的叫做:django.forms。
表单框架最主要的用法是,为每一个将要处理的HTML的``<Form>``定义一个Form类。在这个例子中,我们只有一个``<Form>``,因此我们只需定义一个Form类。这个类可以存在于任何地方,甚至直接写在``views.py``文件里也行,但是社区的惯例是把Form类都放到一个文件中:forms.py。在存放``views.py``的目录中,创建这个文件,然后输入:
fromdjangoimportforms classContactForm(forms.Form): subject=forms.CharField() email=forms.EmailField(required=False) message=forms.CharField()
这看上去简单易懂,并且很像在模块中使用的语法。表单中的每一个字段(域)作为Form类的属性,被展现成Field类。这里只用到CharField和EmailField类型。每一个字段都默认是必填。要使email成为可选项,我们需要指定required=False。
让我们钻研到Python解释器里面看看这个类做了些什么。它做的第一件事是将自己显示成HTML:
>>>fromcontact.formsimportContactForm >>>f=ContactForm() >>>printf <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></tr>
为了便于访问,Django用``<label>``标志,为每一个字段添加了标签。这个做法使默认行为尽可能合适。
默认输出按照HTML的<``table``>格式,另外有一些其它格式的输出:
>>>printf.as_ul() <li><labelfor="id_subject">Subject:</label><inputtype="text"name="subject"id="id_subject"/></li> <li><labelfor="id_email">Email:</label><inputtype="text"name="email"id="id_email"/></li> <li><labelfor="id_message">Message:</label><inputtype="text"name="message"id="id_message"/></li> >>>printf.as_p() <p><labelfor="id_subject">Subject:</label><inputtype="text"name="subject"id="id_subject"/></p> <p><labelfor="id_email">Email:</label><inputtype="text"name="email"id="id_email"/></p> <p><labelfor="id_message">Message:</label><inputtype="text"name="message"id="id_message"/></p>
请注意,标签<table>、<ul>、<form>的开闭合标记没有包含于输出当中,这样你就可以添加额外的行或者自定义格式。
这些类方法只是一般情况下用于快捷显示完整表单的方法。你同样可以用HTML显示个别字段:
>>>printf['subject'] <inputtype="text"name="subject"id="id_subject"/> >>>printf['message'] <inputtype="text"name="message"id="id_message"/>
Form对象做的第二件事是校验数据。为了校验数据,我们创建一个新的对Form象,并且传入一个与定义匹配的字典类型数据:
>>>f=ContactForm({'subject':'Hello','email':'adrian@example.com','message':'Nicesite!'})
一旦你对一个Form实体赋值,你就得到了一个绑定form:
>>>f.is_bound True
调用任何绑定form的is_valid()方法,就可以知道它的数据是否合法。我们已经为每个字段传入了值,因此整个Form是合法的:
>>>f.is_valid() True
如果我们不传入email值,它依然是合法的。因为我们指定这个字段的属性required=False:
>>>f=ContactForm({'subject':'Hello','message':'Nicesite!'}) >>>f.is_valid() True
但是,如果留空subject或message,整个Form就不再合法了:
>>>f=ContactForm({'subject':'Hello'}) >>>f.is_valid() False >>>f=ContactForm({'subject':'Hello','message':''}) >>>f.is_valid() False
你可以逐一查看每个字段的出错消息:
>>>f=ContactForm({'subject':'Hello','message':''}) >>>f['message'].errors [u'Thisfieldisrequired.'] >>>f['subject'].errors [] >>>f['email'].errors []
每一个邦定Form实体都有一个errors属性,它为你提供了一个字段与错误消息相映射的字典表。
>>>f=ContactForm({'subject':'Hello','message':''}) >>>f.errors {'message':[u'Thisfieldisrequired.']}
最终,如果一个Form实体的数据是合法的,它就会有一个可用的cleaned_data属性。这是一个包含干净的提交数据的字典。Django的form框架不但校验数据,它还会把它们转换成相应的Python类型数据,这叫做清理数据。
>>>f=ContactForm({subject':Hello,email:adrian@example.com,message:Nicesite!}) >>>f.is_valid() True >>>f.cleaned_data {message':uNicesite!,email:uadrian@example.com,subject:uHello}
我们的contactform只涉及字符串类型,它们会被清理成Unicode对象。如果我们使用整数型或日期型,form框架会确保方法使用合适的Python整数型或datetime.date型对象。