一、django forms
1、特点
django forms是Django的表单处理库。依赖HttpRequest,它具有如下特点:
(1)、快速自动生成HTML表单
(2)、表单数据校验
(3)、错误信息提示
(4)、自动转换为python数据格式
2、探究form类
1 #coding=utf-8 2 #forms.py 3 from django import forms 4 5 class ContactForm(forms.Form): 6 name = forms.CharField(max_length=30) 7 age = forms.IntegerField() 8 email = forms.EmailField(required=False) 9
为每一个将要处理的HTML的`` <Form>`` 定义一个Form类,表单中的每一个字段(域)作为Form类的属性,被展现
成Field类,如果指定非必填可required=False。
(1)、form类所做的就是第一步就是快速生成html代码,如下:
#form app下定义forms.py >>> from form.forms import ContactForm >>> f = ContactForm >>> print f <class 'form.forms.ContactForm'> #对象 >>> f = ContactForm() >>> print f <tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="tex t" name="name" maxlength="30" /></td></tr> <tr><th><label for="id_age">Age:</label></th><td><input type="text" name="age" i d="id_age" /></td></tr> <tr><th><label for="id_email">Email:</label></th><td><input type="text" name="em ail" id="id_email" /></td></tr> #逐个输出 >>> for obj in f: ... print obj ... <input id="id_name" type="text" name="name" maxlength="30" /> <input type="text" name="age" id="id_age" /> <input type="text" name="email" id="id_email" /> #as_table() >>> print f.as_table() <tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="tex t" name="name" maxlength="30" /></td></tr> <tr><th><label for="id_age">Age:</label></th><td><input type="text" name="age" i d="id_age" /></td></tr> <tr><th><label for="id_email">Email:</label></th><td><input type="text" name="em ail" id="id_email" /></td></tr> #as_p() >>> print f.as_p() <p><label for="id_name">Name:</label> <input id="id_name" type="text" name="name " maxlength="30" /></p> <p><label for="id_age">Age:</label> <input type="text" name="age" id="id_age" /> </p> <p><label for="id_email">Email:</label> <input type="text" name="email" id="id_e mail" /></p> #as_ul() >>> print f.as_ul() <li><label for="id_name">Name:</label> <input id="id_name" type="text" name="nam e" maxlength="30" /></li> <li><label for="id_age">Age:</label> <input type="text" name="age" id="id_age" / ></li> <li><label for="id_email">Email:</label> <input type="text" name="email" id="id_ email" /></li> #指定输出 >>> print f['name'] <input id="id_name" type="text" name="name" maxlength="30" /> >>>
(2)、数据校验与错误信息提示
创建form对象,传入字典类型数据
>>>f=ContactForm({'name':'BeginMan','age':100,'email':'[email protected]'}) >>> f.is_bound #一旦你对一个Form实体赋值,你就得到了一个绑定form True >>> f.is_valid() #调用任何绑定form的is_valid()方法,就可以知道它的数据是否合法 True >>> f = ContactForm({'name':'BeginMan'}) >>> f.is_valid() False #每一个邦定Form实体都有一个errors属性,它提供了一个字段与错误消息相映射的字典表。 >>> f.errors {'age': [u'This field is required.']} >>> f.errors['age'] [u'This field is required.'] >>> f['age'].errors [u'This field is required.'] >>>
(3)、转换处理
如果form对象的数据合法,则有cleaned_data属性,一个清理过的提交数据字典。
>>> f.cleaned_data {'age': 100, 'name': u'BeginMan', 'email': u'[email protected]'}
当然。我们也可以在其生成的html表单中,看到原始效果
>>> for obj in f: ... print obj ... <input id="id_name" type="text" name="name" value="BeginMan" maxlength="30" /> <input type="text" name="age" value="100" id="id_age" /> <input type="text" name="email" value="[email protected]" id="id_email" />
二、Forms API
参考:https://docs.djangoproject.com/en/1.2/ref/forms/api/
这里列出重点:
1、绑定和未绑定(unbound)表单的区别
Form.is_bound
相同点:
(1)、都是表单实例
(2)、都可以生成html表单代码
(3)、都有相关属性方法
不同点:
(1)、绑定的表单,有绑定的数据,可以验证,rendering the form as HTML with the data displayed in the HTML.
(2)、未绑定的表单,不能验证,为空或默认值。
>>> f = ContactForm()#定义未绑定数据的form >>> f.is_bound False >>> data = {'name':'BeginMan','age':22,'email':'[email protected]'} >>> boundF = ContactForm(data)#绑定数据 >>> boundF.is_bound True >>> print f <tr><th><label for="id_name">Name:</label></th><td><input id="id_name" typt" name="name" maxlength="30" /></td></tr> <tr><th><label for="id_age">Age:</label></th><td><input type="text" name="d="id_age" /></td></tr> <tr><th><label for="id_email">Email:</label></th><td><input type="text" naail" id="id_email" /></td></tr> >>> print boundF <tr><th><label for="id_name">Name:</label></th>
<td><input id="id_name" typt" name="name" value="BeginMan" maxlength="30" /></td></tr> <tr><th><label for="id_age">Age:</label></th><td><input type="text" name="alue="22" id="id_age" /></td></tr> <tr><th><label for="id_email">Email:</label></th><td><input type="text" naail" value="[email protected]" id="id_email" /></td></tr> >>>
绑定空数据
>>> f=ContactForm({}) >>> f.is_bound True >>>
那么如果在post表单数据,则可以这样绑定:
if request.method == 'POST': form = ContactForm(request.POST) #绑定post数据 .... else: form = ContactForm() #如果表单未被提交,则一个未绑定的表单实例被创建
2、Form.initial表单初始化。
我认为就是给表单绑定一些数据,用于特定显示或处理。当然这些可有可无,如提示等。如果提供,则是包含表单字段的字典类型。如:
f = ContactForm(initial={'name':'Hi,here','email':'@'})
可以在表单类中初始化,也可以在表单对象中初始化,对于同一个字段的初始化,后者覆盖前者。
>>> class CommentForm(forms.Form): ... name = forms.CharField(initial='class')#initial初始化 ... url = forms.URLField() ... comment = forms.CharField() #表单对象中初始化 >>> f = CommentForm(initial={'name': 'instance'}, auto_id=False) >>> print f <tr><th>Name:</th><td><input type="text" name="name" value="instance" /></td></tr> <tr><th>Url:</th><td><input type="text" name="url" /></td></tr> <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
对于这种初始化,在前端显示也有涉及,如:
if request.method == 'POST': form = ContactForm(request.POST) #绑定post数据 .... else: #如果表单未被提交,则一个未绑定的表单实例被创建 form = ContactForm(initial={'name':'Hi,here','email':'@'}) return render_to_response('form/form.html',{'form':form})
则在页面显示如下,
#template form.html {{form.as_table}}
注意:
These values are only displayed for unbound forms, and they’re not used as fallback values if a particular value isn’t provided.
3、Form.cleaned_data
始终要明白,当通过一系列的数据来创建表单对象,并验证通过的时候,就要使用cleaned_data属性进行‘清理工作’,所谓的清理就是对给定的数据对应到python类型。
返回的是一组被清理过的字典类型数据。
#对应上面的boundF >>> boundF.cleaned_data {'age': 22, 'name': u'BeginMan', 'email': u'[email protected]'}
4、自定义样式
这里的样式是自动生成的html代码样式,如各个表单控件的id,错误标签的class等。最初如下:
>>> data={'name':'mx'} >>> f = ContactForm(data) >>> print f <tr> <th><label for="id_name">Name:</label></th> <!--默认都带有label-->
<!--id 都是以'id_'+字段名 组成的-->
<td><input id="id_name" type="text" name="name" value="mx" maxlength="30" /></td> </tr> <tr> <th><label for="id_age">Age:</label></th> <td> <ul class="errorlist"> <!--默认错误标签ul的类是‘errorlist’--> <li>This field is required.</li> <!--显示错误信息--> </ul> <input type="text" name="age" id="id_age" /> </td> </tr> <tr> <th><label for="id_email">Email:</label></th> <td><input type="text" name="email" id="id_email" /></td> </tr>
那么现在有3个疑问?:
(1)、能否改变错误类
(2)、能否改变id
(3)、能否去掉label
针对以上三点,一一解答:
(1)、自定义验证样式类:
如果验证不通过,则会输出错误,对应的有“必需”、‘错误’两项,那么就在这两项中做文章。
class ContactForm(Form): ....... error_css_class = 'error'#当提示错误的时候,使用的是error类 required_css_class = 'required'#当提示必须的时候,使用required类
如:
>>> f = ContactForm(data) >>> print f.as_table() <tr class="required"><th><label for="id_name">Name:</label> ...
By default, forms use django.forms.util.ErrorList to format validation errors.
如果想换一种方式,可以自定义错误显示
#forms.py #自定义错误列表格式 from django.forms.util import ErrorList class DivErrorList(ErrorList): def __unicode__(self): return self.as_divs() def as_divs(self): if not self: return u'' return u'<div class="errorlist">%s</div>' % ''.join([u'<div class="error">%s</div>' %e for e in self])
>>> from form.forms import ContactForm,DivErrorList #导入 >>> data = {'name':False,'age':'22','email':'sd'} >>> f = ContactForm(data, auto_id=False, error_class=DivErrorList) >>> print f.as_p() <p class="required">Name: <input type="text" name="name" value="False" maxlength="30" /></p> <p class="required">Age: <input type="text" name="age" value="22" /></p> <div class="errorlist"><div class="error">Enter a valid e-mail address.</div></div><!--自定义错误样式--> <p class="error">Email: <input type="text" name="email" value="sd" /></p>
(2)、控制label和id
可以使用auto_id变量控制label和id ,auto_id必须为True、False或字符串。
>>> f = ContactForm(auto_id=False)#省略了id和label >>> print f.as_table() <tr><th>Name:</th><td><input type="text" name="name" maxlength="30" /></td></tr> ...... >>> print f.as_ul() <li>Name: <input type="text" name="name" maxlength="30" /></li> ....... >>> print f.as_p() <p>Name: <input type="text" name="name" maxlength="30" /></p> ......
如果auto_id = True 则会自动使用label,且id名称为 它们的字段名
>>> f = ContactForm(auto_id=True) >>> print f <tr><th><label for="name">Name:</label></th><td><input id="name" type="text" name="name" maxlength="30" /></td></tr> 。。。。
auto_id使用格式化字符串(%s)
>>> f = ContactForm(auto_id='id_for_%s') >>> print f.as_p() <p><label for="id_for_name">Name:</label> <input id="id_for_name" type="text" name="name" maxlength="30" /></p> <p><label for="id_for_age">Age:</label> <input type="text" name="age" id="id_for_age" /></p> <p><label for="id_for_email">Email:</label> <input type="text" name="email" id="id_for_email" /></p>
通过上面我们知道,默认的auto_id使用格式化字符串 auto_id = 'id_%s'
接下来控制Label后缀,通过label_suffix 进行控制
>>> f = ContactForm(label_suffix='OK') >>> print f.as_p() <p><label for="id_name">NameOK</label> <input id="id_name" type="text" name="name" maxlength="30" /></p> <p><label for="id_age">AgeOK</label> <input type="text" name="age" id="id_age" /></p> <p><label for="id_email">EmailOK</label> <input type="text" name="email" id="id_email" /></p> >>>