django中表单处理
在web端与后端交互时,我们除了使用html原生的form标签,还可以使用django自带的表单。
Django 提供广泛的工具和库来帮助你构建表单来接收网站访问者的输入,然后处理以及响应输入。
HTML表单
在HTML中,表单的作用是收集标签中的内容,<form>...</form>
中间可以由访问者添加类似于文本,选择,或者一些控制模块等等.然后这些内容将会被送到服务端
某些表单的元素 —— 文本输入和复选框 —— 非常简单而且内建于HTML 本身。 其他的复杂得多;弹出日期选择器或允许您移动滑块或操纵控件的界面通常将使用JavaScript和CSS以及HTML表单<input>
元素来实现这些效果。
与<input>
元素一样,一个表单必须指定两样东西:
- 目的地:响应用户输入数据的URL
- 方式:发送数据所使用的HTTP 方法
GET和POST方法
Django 的登录表单使用POST
方法,在这个方法中浏览器组合表单数据、对它们进行编码以用于传输、将它们发送到服务器然后接收它的响应。
相反,GET
组合提交的数据为一个字符串,然后使用它来生成一个URL。 这个URL 将包含数据发送的地址以及数据的键和值。
post和get用于不同的目的:
用于改变系统状态的请求 —— 例如,给数据库带来变化的请求 —— 应该使用POST
。 GET
只应该用于不会影响系统状态的请求。
GET
还不适合密码表单,因为密码将出现在URL 中,以及浏览器的历史和服务器的日志中,而且都是以普通的文本格式。 它还不适合数据量大的表单和二进制数据,例如一张图片。 使用GET
请求作为管理站点的表单具有安全隐患:攻击者很容易模拟表单请求来取得系统的敏感数据。 POST
,如果与其它的保护措施结合将对访问提供更多的控制,例如Django 的CSRF protection。
另一个方面,GET
适合网页搜索这样的表单,因为这种表示一个GET
请求的URL 可以很容易地作为书签、分享和重新提交
django中的表单
在一个Web 应用中,"表单"可能指HTML <form>
、或者生成它的Django 的Form
、或者提交时发送的结构化数据、或者这些部分的总和。
django的FORM类
表单系统的核心部分是Django 的Form
类。 Django 的模型描述一个对象的逻辑结构、行为以及展现给我们的方式,与此类似,Form
类描述一个表单并决定它如何工作和展现。
就像模型类的属性映射到数据库的字段一样,表单类的字段会映射到HTML 的<input>
表单的元素。 (ModelForm
通过一个Form
映射模型类的字段到HTML 表单的<input>
元素;Django 的Admin 站点就是基于这个)。
一个表单的字段本身就是类;他们管理表单数据,并在提交表单时执行验证。 DateField
和FileField
处理的数据类型差别很大,必须完成不同的事情。
表单字段在浏览器中呈现给用户的是一个HTML 的“widget” —— 用户界面的一个片段。 每个字段类型都有一个合适的默认Widget class,需要时可以覆盖。
构建表单
构建一个表单,获取用户的输入信息即可!
正常使用html写django提交表单如下:
<form action="/info/" method="post">
<label for="meg">请输入信息</label>
<input type="text" id="meg"><br>
<input type="submit" value="提交">
{% csrf_token %}
</form>
随着业务逻辑的应用,我们可能需要越来越多的input标签,并且还需要对标签输入的内容做一些处理等等。因此为了更方便的处理表单提交,django引入了FORM类。
一个简单的表单应用如下:
因为比较简单我们把Form表单与视图函数写在了一个文件中(不推荐):
# *-* coding:utf-8 *-*
from django.shortcuts import render # Create your views here.
from django import forms class InfoForm(forms.Form):
info = forms.CharField(label=u"用户信息", max_length=100) #注意这里的类属性定义的info不能省略,不然不会再前端显示 infoform = InfoForm() #实例化表单数据,并且把表单实例对象传递给html页面 def info(request):
return render(request, "info.html", {"infoform": infoform})
它定义一个Form
类,只带有一个字段(info
)。 我们已经对这个字段使用一个人性化的标签,当渲染时它将出现在<label>
中(在这个例子中,即使我们省略它,我们指定的label
还是会自动生成)。
字段允许的最大长度通过max_length
定义。 它完成两件事情。 首先,它在HTML 的<input>
上放置一个maxlength="100"
(这样浏览器将在第一时间阻止用户输入多于这个数目的字符)。 它还意味着当Django 收到浏览器发送过来的表单时,它将验证数据的长度。
Form
的实例具有一个is_valid()
方法,它为所有的字段运行验证的程序。 当调用这个方法时,如果所有的字段都包含合法的数据,它将:
- 返回
True
- 将表单的数据放到
cleaned_data
属性中。
前端代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/info/" method="post">
{{ infoform }}
<input type="submit" value="提交">
{% csrf_token %} #这个是django为了表单的安全验证必须添加,若不想添加可以现在中间件哪里注释掉对应的验证。
</form>
</body>
</html>
展示效果如下:
格式需要自己写!
上面我们把表单的数据提交了,那么在后台改如何处理呢?我们知道视图层的作用就是作为前后端交互的中间层,那么表单提交的数据自然也是在视图层处理了。
# *-* coding:utf-8 *-*
from django.shortcuts import render, HttpResponse # Create your views here.
from django import forms class InfoForm(forms.Form):
info = forms.CharField(label=u"用户信息 ", max_length=100) infoform = InfoForm() def info(request):
if request.method == "GET": #若是GET访问,则是直接访问上面这个表单页面
return render(request, "info.html", {"infoform": infoform})
elif request.method == "POST": #若是POST访问,然后提取数据,处理数据
form = InfoForm(request.POST) #首先把request.POST对象作为参数传递给InfoForm来实例化,通过表单的方式来处理数据
if form.is_valid(): #is_valid()方法上面提到过、
print "OK"
print form.cleaned_data #打印出表单提交的数据,返回的是一个字典。
return HttpResponse("<h1>提交成功</h1>")
else:
return HttpResponse("error")
打印的结果是一个字典:
{'info': u'i have a dream'} #这里使用了cleaned_data方法,这个方法返回的是表单提交数据信息(我们需要的数据),这里仅仅有我们需要的用户输入的信息。
#当然这里的表单处理,依然可以使用之前的request.POST方法来处理。
视图的整个逻辑是这样的:
如果访问视图的是一个GET 请求,它将创建一个空的表单实例并将它放置到要渲染的模板的上下文中。 这是我们在第一次访问该URL 时预期发生的情况。 如果使用POST请求提交表单,该视图将再次创建一个表单实例,并使用请求中的数据填充表单:形式 = NameForm(request.POST)这被称为“将数据绑定到表单”(现在是绑定的形式)。 我们调用窗体的is_valid()方法;如果不是True,我们返回到表单的模板。 这时表单不再为空(未绑定),所以HTML 表单将用之前提交的数据填充,然后可以根据要求编辑并改正它。 如果True 为is_valid(),我们将能够在cleaned_data 属性中找到所有合法的表单数据。 在发送HTTP 重定向给浏览器告诉它下一步的去向之前,我们可以用这个数据来更新数据库或者做其它处理。
上面通过了一个简单的实例说明了django表单的使用流程,django表单的用法还是很强大的,下面会详细说明其用法。
django的forms类
所有的表单类都作为django.forms.Form
的子类创建,包括你在Django 管理站点中遇到的ModelForm。
绑定和未绑定数据的表单:
- 不包含数据的表单称为未绑定表单。 当render给用户时,它将为空或包含默认的值。
- 包含数据的表单称为绑定表单,因此可以用来检验数据是否合法。 如果渲染一个不合法的绑定的表单,它将包含内联的错误信息,告诉用户如何纠正数据。
表单的is_bound
属性将告诉你一个表单是否具有绑定的数据。
把上面视图函数中的print “OK”位置换成下面的:
print form.is_bound #表单已经绑定则返回True,否则返回False ##结果
{'info': u'i have a dream'} #这个为print cleanted_data打印的结果
True
不管表单提交的是什么数据,一旦通过调用is_valid()
成功验证(is_valid()
返回True
),验证后的表单数据将位于form.cleaned_data
字典中。 这些数据已经为你转换好为Python 的类型。
表单渲染
上面的实例中,我们infoform表单被渲染为label标签和input标签,这两个标签需要放入form表单中才可以使用。这是表单的默认渲染方式。
我们还可以有以下的渲染方式:
{{ form.as_table }} 以表格的形式将它们渲染在<tr> 标签中
{{ form.as_p }} 将它们渲染在<p> 标签中
{{ form.as_ul }} 将它们渲染在<li> 标签中 #实例
<ul>
{{ infoform.as_ul }}
</ul>
分解form表单:
上面在前端上面引用时,我们直接引用了{{ infoform }}的形式,但是这个变量包含了许多数据,有时候我们为了自己渲染每个部分,需要单独的提取某个部分,然后处理:
属性 说明
{{ field.label }} 字段对应的label信息
{{ field.label_tag }} 自动生成字段的label标签,注意与{{ field.label }}的区别,它包含表单的label_suffix
。 例如,默认的label_suffix
是一个冒号:
{{ field.id_for_label }} 自定义字段标签的id
{{ field.value }} 当前字段的值,比如一个Email字段的值someone@example.com
{{ field.html_name }} 指定字段生成的input标签中name属性的值
{{ field.help_text }} 字段的帮助信息
{{ field.errors }} 包含错误信息的元素
{{ field.is_hidden }} 用于判断当前字段是否为隐藏的字段,如果是,返回True
{{ field.field }} 返回字段的参数列表。例如{{ char_field.field.max_length }}
隐藏字段的处理
如果你正在手工布局模板中的一个表单,而不是依赖Django 默认的表单布局,你可能希望将<input type="hidden">
字段与非隐藏的字段区别对待。 例如,因为隐藏的字段不会显示,在该字段旁边放置错误信息可能让你的用户感到困惑 —— 所以这些字段的错误应该有区别地来处理。
Django 提供两个表单方法,它们允许你独立地在隐藏的和可见的字段上迭代:visible_fields()
和hidden_fields()
。
{# Include the hidden fields #} #注释信息
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{# Include the visible fields #} #注释信息
{% for field in form.visible_fields %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
这个示例没有处理隐藏字段中的任何错误信息。 通常,隐藏字段中的错误意味着表单被篡改,因为正常的表单填写不会改变它们。 然而,你也可以很容易地为这些表单错误插入一些错误信息显示出来。
重用表单渲染
如果你的网站在多个地方对表单使用相同的渲染逻辑,你可以保存表单的循环到一个单独的模板中来减少重复,然后在其它模板中使用include
标签来重用它:
# In your form template:
{% include "form_snippet.html" %} # In form_snippet.html:
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
如果传递到模板上下文中的表单对象具有一个不同的名称,你可以使用include
标签的with
参数来对它起个别名:
{% include "form_snippet.html" with form=comment_form %}
django表单的字段:https://yiyibooks.cn/xx/Django_1.11.6/ref/forms/fields.html
django中表单处理的更多相关文章
- 118.django中表单的使用方式
表单 HTML中的表单: 从前端来说,表单就是用来将数据提交给服务器的,不管后台使用的是django还是php等其他的语言.只要把input标签放在form标签中,然后再添加一个提交的按钮,就可以将i ...
- Django中表单的用法深探
[转载说明:原文排版不是很好,为方便阅读,改进了排版] django的表单设计真的很棒,涉及非常多的功能,今天介绍django较为主流的几种表单使用方法.注:本文中表单与form通用.模型与model ...
- Django表单介绍
HTML 表单 在HTML中,表单是<form>...</form> 之间元素的集合,它们允许访问者输入文本.选择选项.操作对象和控制等等,然后将信息发送回服务器. 某些表单的 ...
- python3之Django表单(一)
1.HTML中的表单 在HTML种,表单是在<form>...</form>种的元素,它允许用户输入文本,选择选项,操作对象等,然后发送这些数据到服务器 表单元素允许用户在表单 ...
- 第四章:Django表单 - 3:Django表单字段汇总
Field.clean(value)[source] 虽然表单字段的Field类主要使用在Form类中,但也可以直接实例化它们来使用,以便更好地了解它们是如何工作的.每个Field的实例都有一个cle ...
- 关于struts2中表单提交时,中文乱码问题的解决
http://blog.csdn.net/hjw506848887/article/details/8966194 今天写项目时,突然遇到了struts2中表单提交的中文乱码问题,调了好久就是不知道答 ...
- HTML5中表单验证的8种方法(转)
在深人探讨表单验证之前,让我们先思考一下表单验证的真实含义.就其核心而言,表单验证是一套系统,它为终端用户检测无效的控件数据并标记这些错误.换言之,表单验证就是在表单提交服务器前对其进行一系列的检查并 ...
- python 全栈开发,Day111(客户管理之 编辑权限(二),Django表单集合Formset,ORM之limit_choices_to,构造家族结构)
昨日内容回顾 1. 权限系统的流程? 2. 权限的表有几个? 3. 技术点 中间件 session orm - 去重 - 去空 inclusion_tag filter 有序字典 settings配置 ...
- django表单的api
django表单的api,参考文档:https://yiyibooks.cn/xx/Django_1.11.6/ref/forms/api.html 绑定与未绑定形式: Form要么是绑定的,要么是未 ...
随机推荐
- jenkins 邮箱配置---腾讯企业邮箱
一,简单设置 1.登陆jenkins--> 系统管理 ---> 系统设置 2.邮箱就是发送者的邮箱,密码是登陆邮箱的密码 3.设置完以后,可以点击‘test configuration’, ...
- vue2.0--请求数据
vue中用vue-reouse请求来的数据,会被封装一层,如下图res:
- MySQL--4操作数据表中的记录小结
最常用,最复杂的语句: 每一项的: 表的参照 From 条件 WHERE 进行记录的分组 GROUP BY 分组的时候对分组的条件进行设定 HAVING 对结果进行排序 ORDER BY ...
- 彻底理解什么是原型链,prototype和__proto__的区别以及es5中的继承
再讲一遍好了( 参考https://blog.csdn.net/cc18868876837/article/details/81211729 https://blog.csdn.net/lc23742 ...
- js函数中写默认值的几种方式(常见的)
<script> <!--第一种写法,我更喜欢第一种写法直观一些--> function Person(name){ this.name = name || '默认名字乔丹'; ...
- 多模块项目提示“Module ** must not contain source root **. The root already belongs to module **”的解决办法
从Project Structure里添加模块,完了点击Apply时弹出提示: Module "paycode"must not contain source root " ...
- node.js初识09
1.node_module文件夹 如果你的require中没有写./,那么Node.js将该文件视为node_modules目录下的一个文件. 2.package.json文件 如果使用文件夹来统筹管 ...
- Lambda引言
Lambda表达式:可以方便我们把方法当做参数传递 package airycode_java8.nice1; import org.junit.Test; import java.util.*; / ...
- c++中istream类型到bool类型的隐式转换
事情的起因是见到了这种用法: while(cin>>m>>n&&m&&n) { } 现在分析一下,cin>>m>>n返回 ...
- linux下安装mysql等信息
1.安装 apt-get update;// 第一次的时候,你更新一下你的软件包的源地址数据; apt-get install mysql-server 2.账号登陆 mysql -h localho ...