详解Django中的form库的使用


Posted in Python onJuly 18, 2015

Django带有一个form库,称为django.forms,这个库可以处理我们本章所提到的包括HTML表单显示以及验证。 接下来我们来深入了解一下form库,并使用她来重写contact表单应用。

Django的newforms库

在Django社区上会经常看到django.newforms这个词语。当人们讨论django.newforms,其实就是我们本章里面介绍的django.forms。

改名其实有历史原因的。 当Django一次向公众发行时,它有一个复杂难懂的表单系统:django.forms。后来它被完全重写了,新的版本改叫作:django.newforms,这样人们还可以通过名称,使用旧版本。 当Django 1.0发布时,旧版本django.forms就不再使用了,而django.newforms也终于可以名正言顺的叫做:django.forms。

表单框架最主要的用法是,为每一个将要处理的HTML的`` <Form>`` 定义一个Form类。 在这个例子中,我们只有一个`` <Form>`` ,因此我们只需定义一个Form类。 这个类可以存在于任何地方,甚至直接写在`` views.py`` 文件里也行,但是社区的惯例是把Form类都放到一个文件中:forms.py。在存放`` views.py`` 的目录中,创建这个文件,然后输入:

from django import forms

class ContactForm(forms.Form):
  subject = forms.CharField()
  email = forms.EmailField(required=False)
  message = forms.CharField()

这看上去简单易懂,并且很像在模块中使用的语法。 表单中的每一个字段(域)作为Form类的属性,被展现成Field类。这里只用到CharField和EmailField类型。 每一个字段都默认是必填。要使email成为可选项,我们需要指定required=False。

让我们钻研到Python解释器里面看看这个类做了些什么。 它做的第一件事是将自己显示成HTML:

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

为了便于访问,Django用`` <label>`` 标志,为每一个字段添加了标签。 这个做法使默认行为尽可能合适。

默认输出按照HTML的<`` table`` >格式,另外有一些其它格式的输出:

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

请注意,标签<table>、<ul>、<form>的开闭合标记没有包含于输出当中,这样你就可以添加额外的行或者自定义格式。

这些类方法只是一般情况下用于快捷显示完整表单的方法。 你同样可以用HTML显示个别字段:

>>> print f['subject']
<input type="text" name="subject" id="id_subject" />
>>> print f['message']
<input type="text" name="message" id="id_message" />

Form对象做的第二件事是校验数据。 为了校验数据,我们创建一个新的对Form象,并且传入一个与定义匹配的字典类型数据:

>>> f = ContactForm({'subject': 'Hello', 'email': 'adrian@example.com', 'message': 'Nice site!'})

一旦你对一个Form实体赋值,你就得到了一个绑定form:

>>> f.is_bound
True

调用任何绑定form的is_valid()方法,就可以知道它的数据是否合法。 我们已经为每个字段传入了值,因此整个Form是合法的:

>>> f.is_valid()
True

如果我们不传入email值,它依然是合法的。因为我们指定这个字段的属性required=False:

>>> f = ContactForm({'subject': 'Hello', 'message': 'Nice site!'})
>>> 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'This field is required.']
>>> f['subject'].errors
[]
>>> f['email'].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': uNice site!, email: uadrian@example.com, subject: uHello}

我们的contact form只涉及字符串类型,它们会被清理成Unicode对象。如果我们使用整数型或日期型,form框架会确保方法使用合适的Python整数型或datetime.date型对象。

Python 相关文章推荐
Python实现批量把SVG格式转成png、pdf格式的代码分享
Aug 21 Python
解决Python中由于logging模块误用导致的内存泄露
Apr 23 Python
python调用fortran模块
Apr 08 Python
Python二叉树定义与遍历方法实例分析
May 25 Python
Python爬取qq空间说说的实例代码
Aug 17 Python
flask框架jinja2模板与模板继承实例分析
Aug 01 Python
python安装gdal的两种方法
Oct 29 Python
Python3.6安装卸载、执行命令、执行py文件的方法详解
Feb 20 Python
Django之全局使用request.user.username的实例详解
May 14 Python
完美解决Django2.0中models下的ForeignKey()问题
May 19 Python
Python爬虫之Selenium实现窗口截图
Dec 04 Python
Python捕获、播放和保存摄像头视频并提高视频清晰度和对比度
Apr 14 Python
在Django框架中编写Contact表单的教程
Jul 17 #Python
简单解析Django框架中的表单验证
Jul 17 #Python
改进Django中的表单的简单方法
Jul 17 #Python
Python的Django框架中的表单处理示例
Jul 17 #Python
Python中max函数用法实例分析
Jul 17 #Python
详解Django中Request对象的相关用法
Jul 17 #Python
Python实现SVN的目录周期性备份实例
Jul 17 #Python
You might like
Apache2中实现多网站域名绑定的实现方法
2011/06/01 PHP
thinkphp3.0 模板中函数的使用
2012/11/13 PHP
typecho插件编写教程(四):插件挂载
2015/05/28 PHP
php HTML无刷新提交表单
2016/04/05 PHP
Ecshop 后台添加新功能栏目及管理权限设置教程
2017/11/21 PHP
PHP生成随机数的方法总结
2018/03/01 PHP
php中访问修饰符的知识点总结
2019/01/27 PHP
tp5递归 无限级分类详解
2019/10/18 PHP
JS仿百度搜索自动提示框匹配查询功能
2013/11/21 Javascript
js购物车实现思路及代码(个人感觉不错)
2013/12/23 Javascript
JS实现一个按钮的方法
2015/02/05 Javascript
JavaScript实现点击文字切换登录窗口的方法
2015/05/11 Javascript
JavaScript实现网页加载进度条代码超简单
2015/09/21 Javascript
深入理解Node.js的HTTP模块
2016/10/12 Javascript
JavaScript实现页面无操作倒计时退出
2016/10/22 Javascript
详解AngularJS中$filter过滤器使用(自定义过滤器)
2017/02/04 Javascript
解决vue build打包之后首页白屏的问题
2018/03/06 Javascript
[48:00]完美世界DOTA2联赛循环赛 Forest vs Inki BO2第二场 11.04
2020/11/04 DOTA
分享一个可以生成各种进制格式IP的小工具实例代码
2017/07/28 Python
python单线程文件传输的实例(C/S)
2019/02/13 Python
Python 计算任意两向量之间的夹角方法
2019/07/05 Python
Python利用imshow制作自定义渐变填充柱状图(colorbar)
2020/12/10 Python
CSS3支持IE6, 7, and 8的边框border属性
2012/12/28 HTML / CSS
英国第一的购买便宜玩具和游戏的在线购物网站:Bargain Max
2018/01/24 全球购物
智能家居、吸尘器、滑板车、电动自行车网上购物:Geekmaxi
2021/01/18 全球购物
蛋糕店的商业计划书范文
2014/01/27 职场文书
给老婆的保证书范文
2014/04/28 职场文书
学习党代会心得体会
2014/09/05 职场文书
青年教师个人总结
2015/02/11 职场文书
大学生党员个人总结
2015/02/13 职场文书
办公室主任个人总结
2015/02/28 职场文书
吴仁宝观后感
2015/06/09 职场文书
pytorch损失反向传播后梯度为none的问题
2021/05/12 Python
MySQL为id选择合适的数据类型
2021/06/07 MySQL
sql server删除前1000行数据的方法实例
2021/08/30 SQL Server
浅谈Redis的keys命令到底有多慢
2021/10/05 Redis