在Django的视图中使用form对象的方法


Posted in Python onJuly 18, 2015

在学习了关于Form类的基本知识后,你会看到我们如何把它用到视图中,取代contact()代码中不整齐的部分。 一下示例说明了我们如何用forms框架重写contact():

# views.py

from django.shortcuts import render_to_response
from mysite.contact.forms import ContactForm

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>

看看,我们能移除这么多不整齐的代码! Django的forms框架处理HTML显示、数据校验、数据清理和表单错误重现。

尝试在本地运行。 装载表单,先留空所有字段提交空表单;继而填写一个错误的邮箱地址再尝试提交表单;最后再用正确数据提交表单。 (根据服务器的设置,当send_mail()被调用时,你将得到一个错误提示。而这是另一个问题。)
改变字段显示

你可能首先注意到:当你在本地显示这个表单的时,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)中。 每一个字段类型都拥有一个默认的部件,我们也可以容易地替换掉默认的部件,或者提供一个自定义的部件。

考虑一下Field类表现* 校验逻辑* ,而部件表现* 显示逻辑* 。
设置最大长度

一个最经常使用的校验要求是检查字段长度。 另外,我们应该改进ContactForm,使subject限制在100个字符以内。 为此,仅需为CharField提供max_length参数,像这样:

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)

选项min_length参数同样可用。
设置初始值

让我们再改进一下这个表单:为字subject段添加* 初始值* : "I love your site!" (一点建议,但没坏处。)为此,我们可以在创建Form实体时,使用initial参数:

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!'}**
    )
  return render_to_response('contact_form.html', {'form': form})

现在,subject字段将被那个句子填充。

请注意,传入* 初始值* 数据和传入数据以* 绑定* 表单是有区别的。 最大的区别是,如果仅传入* 初始值* 数据,表单是unbound的,那意味着它没有错误消息。
自定义校验规则

假设我们已经发布了反馈页面了,email已经开始源源不断地涌入了。 这里有一个问题: 一些提交的消息只有一两个字,我们无法得知详细的信息。 所以我们决定增加一条新的校验: 来点专业精神,最起码写四个字,拜托。

我们有很多的方法把我们的自定义校验挂在Django的form上。 如果我们的规则会被一次又一次的使用,我们可以创建一个自定义的字段类型。 大多数的自定义校验都是一次性的,可以直接绑定到form类.

我们希望`` message`` 字段有一个额外的校验,我们增加一个`` clean_message()`` 方法到`` Form`` 类:

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

Django的form系统自动寻找匹配的函数方法,该方法名称以clean_开头,并以字段名称结束。 如果有这样的方法,它将在校验时被调用。

特别地,clean_message()方法将在指定字段的默认校验逻辑执行* 之后* 被调用。(本例中,在必填CharField这个校验逻辑之后。)因为字段数据已经被部分处理,所以它被从self.cleaned_data中提取出来了。同样,我们不必担心数据是否为空,因为它已经被校验过了。

我们简单地使用了len()和split()的组合来计算单词的数量。 如果用户输入字数不足,我们抛出一个forms.ValidationError型异常。这个异常的描述会被作为错误列表中的一项显示给用户。

在函数的末尾显式地返回字段的值非常重要。 我们可以在我们自定义的校验方法中修改它的值(或者把它转换成另一种Python类型)。 如果我们忘记了这一步,None值就会返回,原始的数据就丢失掉了。
指定标签

HTML表单中自动生成的标签默认是按照规则生成的:用空格代替下划线,首字母大写。如email的标签是"Email" 。(好像在哪听到过? 是的,同样的逻辑被用于模块(model)中字段的verbose_name值。 我们在第五章谈到过。)

像在模块中做过的那样,我们同样可以自定义字段的标签。 仅需使用label,像这样:

class ContactForm(forms.Form):
  subject = forms.CharField(max_length=100)
  email = forms.EmailField(required=False, **label='Your e-mail address'** )
  message = forms.CharField(widget=forms.Textarea)

 

Python 相关文章推荐
Python爬虫实例爬取网站搞笑段子
Nov 08 Python
python通过zabbix api获取主机
Sep 17 Python
Scrapy使用的基本流程与实例讲解
Oct 21 Python
使用PyCharm创建Django项目及基本配置详解
Oct 24 Python
DRF跨域后端解决之django-cors-headers的使用
Jan 27 Python
给我一面国旗 python帮你实现
Sep 30 Python
django-crontab实现服务端的定时任务的示例代码
Feb 17 Python
利用Python裁切tiff图像且读取tiff,shp文件的实例
Mar 10 Python
keras多显卡训练方式
Jun 10 Python
Python如何在windows环境安装pip及rarfile
Jun 15 Python
终于搞懂了Keras中multiloss的对应关系介绍
Jun 22 Python
Python尝试实现蒙特卡罗模拟期权定价
Apr 21 Python
详解Django中的form库的使用
Jul 18 #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
You might like
PHP学习之数组的定义和填充
2011/04/17 PHP
PHP中time(),date(),mktime()区别介绍
2013/09/28 PHP
php删除txt文件指定行及按行读取txt文档数据的方法
2017/01/30 PHP
PHP实现生成推广海报的方法详解
2018/03/14 PHP
gearman中任务的优先级和返回状态实例分析
2020/02/27 PHP
JavaScript 异步调用框架 (Part 2 - 用例设计)
2009/08/03 Javascript
javascript获得网页窗口实际大小的示例代码
2013/09/21 Javascript
js获取内联样式的方法
2015/01/27 Javascript
jQuery实现径向动画菜单效果
2015/07/17 Javascript
node.js微信公众平台开发教程
2016/03/04 Javascript
JavaScript中的Object对象学习教程
2016/05/20 Javascript
jQuery的extend方法【三种】
2016/12/14 Javascript
Vue源码探究之状态初始化
2018/11/14 Javascript
运用TensorFlow进行简单实现线性回归、梯度下降示例
2018/03/05 Python
对PyQt5的输入对话框使用(QInputDialog)详解
2019/06/25 Python
python pandas模块基础学习详解
2019/07/03 Python
Django将默认的SQLite更换为MySQL的实现
2019/11/18 Python
python redis 批量设置过期key过程解析
2019/11/26 Python
Python操作MySQL数据库的示例代码
2020/07/13 Python
Vrbo英国:预订度假屋
2020/08/19 全球购物
社区中秋节活动方案
2014/01/29 职场文书
运动会800米加油稿
2014/02/22 职场文书
创业大赛策划书
2014/03/01 职场文书
公司担保书范文
2014/05/21 职场文书
优秀应届生求职信
2014/06/16 职场文书
优秀本科毕业生自荐信
2014/07/04 职场文书
煤矿安全知识竞赛活动总结
2014/07/07 职场文书
励志演讲稿600字
2014/08/21 职场文书
乡镇干部个人对照检查材料(群众路线)
2014/09/26 职场文书
2014年标准化工作总结
2014/12/17 职场文书
2014年语文教师工作总结
2014/12/18 职场文书
2014年个人总结范文
2015/03/09 职场文书
工作违纪的检讨书范文
2019/07/09 职场文书
导游词之无锡丝业博物馆
2019/11/12 职场文书
基于Python编写一个监控CPU的应用系统
2022/06/25 Python
springboot 全局异常处理和统一响应对象的处理方式
2022/06/28 Java/Android