FORM的引入与使用
【0】引入
表单(Form)是网页中用于收集用户输入数据的一种交互元素。通过表单,用户可以输入文本、选择选项、上传文件等操作。表单通常由一个或多个输入字段(Input Field)组成,每个字段都有一个名称(Name)和一个值(Value),用户可以在字段中输入数据。
表单在前端开发中起着非常重要的作用,它可以用于用户注册、登录、提交评论、搜索等各种场景。通过表单,网页可以收集用户的输入数据,并将数据发送给服务器进行处理或存储。
表单的HTML标签是<form>
,它包含了表单中的各个输入字段和提交按钮。<form>
标签的action
属性指定了表单数据提交的目标URL,method
属性指定了提交方法(通常为GET或POST)。
表单中的输入字段可以使用不同的HTML标签来表示,例如:
<input>
标签用于创建文本输入框、密码输入框、单选按钮、复选框等。<select>
标签用于创建下拉列表。<textarea>
标签用于创建多行文本输入框。<button>
标签用于创建提交按钮、重置按钮等。
在后端开发中,表单数据的处理通常由服务器端的代码来完成。服务器端可以使用各种编程语言和框架来接收、验证和处理表单数据。
总结:
表单是网页中用于收集用户输入数据的交互元素,它由输入字段和提交按钮组成。通过表单,用户可以输入数据并将数据提交给服务器进行处理。在前端,表单使用HTML标签表示,在后端,表单数据的处理由服务器端代码完成。
【一】表单的基本功能
<form action="url" method=get|post name="myform" >
</form>
-name:表单提交时的名称
-action:提交到的地址
-method:提交方式,有get和post两种,默认为get
但是我们常用的是post
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title></head>
<body>
<!--定义form表单:form表单会采集包含的有效数据,提交到后端,进行交互-->
<!--
【1】action属性
地址栏信息:
http://127.0.0.1:8020/Form%E8%A1%A8%E5%8D%95/aaa?username=nana&pwd=123123
?之前是提交的资源的目标地址
?之后是提交的具体的数据
http : 信息交互遵照协议 http协议
127.0.0.1 :代表本机的IP地址
8020 :Hbuilder内置服务器的端口号
Form%E8%A1%A8%E5%8D%95:指的是你的项目名字:Form表单
PS:浏览器的地址栏是不支持中文的,都会转成编码传送,如果你在地址栏看到中文,只是当前的那个浏览器给你一个友好的显示
PS:可以使用在线解析工具查看:urlencode
aaa:目标资源 --》去当前项目下找aaa了
?后的内容:
username=nana&pwd=123123
我们写的文本框,密码框等必须要加入一个属性:name
然后name属性和具体录入的信息会拼成一个键值对的形式
多个键值对之间 ,用&符号进行拼接
PS:只有放在form表单中的内容才会被收集并提交
【2】method属性:默认情况下不写method属性的时候就相当于method="get"
get方式:提交数据可见,不安全,提交数据长度有限制,效率高
post方式 :提交数据不可见,安全,提交数据长度没有限制,效率低
-->
<form action="aaa" method="post"> 用户名:<input type="text" name="username"/><br/> 密码:<input type="password"
name="pwd"/><br/>
<!--提交按钮--> <input type="submit"/></form>
用户名2:<input type="text" name="username2"/></body>
</html>
**** 表单是比较重要的HTML元素,块元素,主要作用是向服务端提交数据。结合表单元素input
使用,通过内部的button
按钮提交(type=“submit”)表单数据。
元素/属性 | 描述 | 值/备注 |
---|---|---|
<form> | 表单元素 | |
action | 提交表单的目标(服务端)地址url | |
method | 提交数据的方式,即数据传输的方式 | - get :通过URL提交数据[url]?uname=1&age=2 - post :通过HTTP表单数据提交,键值格式 |
target | 提交数据时打开action url的方式 | - _self :在当前窗口中打开(默认值)- _blank :在新窗口中打开 |
enctype | 编码类型(encode type),规定了form表单在发送到服务器时的编码方式 | - application/x-www-form-urlencoded :编码所有字符(默认)- multipart/form-data :混合类型,用于表单中有文件上传的情况- text/plain :纯文本,空格转换为 “+” 加号,不对特殊字符编码 |
submit() | 提交表单数据,通过JavaScript代码调用 | |
<fieldset> | 表单分组,默认样式为一个框 | 用于语义化地管理表单样式 |
form | <fieldset> 所属的<form> 的id,当<fieldset> 不在<form> 中时使用 | |
disabled | 整个分组都不可用 | |
<legend> | 作为<fieldset> 的标题,显示在框上 | (legend /ˈledʒənd/ 铭文、图例) |
<style>
#form fieldset {
border: 1px solid skyblue;
padding: 20px 10px;
border-radius: 5px;
text-align: center;
margin: 10px 0px;
}
#form fieldset legend {
font-size: 1em;
border: 1px solid rgb(236, 175, 43);
border-radius: 1em;
padding: 3px 15px;
}
</style>
<form id="form" action="#" target="_self" method="post">
<fieldset>
<legend>登录</legend>
<input type="text" name="uname" placeholder="请输入用户名" required maxlength="36">
<input type="password" name="upwd" required maxlength="12" placeholder="输入密码">
<input type="submit" value="submit-登录">
</fieldset>
</form>
注意:**
<form>
提交数据时参数名为表单元素的name,因此表单控件须设置name属性。
get、post区别:
GET | POST | |
---|---|---|
数据位置 | 数据附加在URL的查询参数中 | 数据包含在HTTP请求的body中 |
数据长度 | 有限制,受URL长度限制(最大长度为2048个字符) | 没有限制 |
安全性 | 数据暴露在URL中,不安全 | 数据不会暴露在URL中,相对安全 |
缓存 | 可以被浏览器缓存 | 不能被浏览器缓存 |
刷新 | 刷新页面时会重新发送请求 | 刷新页面时不会重新发送请求 |
后退按钮 | 后退按钮会重新发送请求 | 后退按钮不会重新发送请求 |
数据类型 | 数据以键值对的形式出现在URL中,例如:example.com/?key1=value1&key2=value2 | 数据可以是多种格式,键值对、JSON、XML等等 |
适用性 | 适用于获取数据,如搜索、过滤等操作 | 适用于提交数据,如登录、注册等操作 |
可见性 | 数据可见于URL,可以通过浏览器地址栏查看 | 数据不可见于URL,无法通过浏览器地址栏查看 |
幂等性 | 幂等,多次相同的请求会产生相同的结果 | 非幂等,多次相同的请求可能会产生不同的结果或造成副作用 |
一般来说,对于以下情况,建议使用POST方法:
- 提交敏感数据:如用户的登录信息、支付信息等,使用POST方法可以更安全地传输数据,因为数据不会暴露在URL中。
- 大量数据:由于GET方法有长度限制,当需要传输大量数据时,应该使用POST方法,因为POST方法没有这个限制。
- 数据更新:当进行数据的创建、修改、删除等操作时,推荐使用POST方法,因为这些操作会对服务器端的资源进行变动。
- 需要加密传输:如果需要加密传输数据,POST方法相对于GET方法更容易实现加密。
而对于以下情况,建议使用GET方法:
- 获取数据:如搜索、过滤等操作,使用GET方法更为合适,因为GET方法可以将参数直接附加在URL中,便于查看和分享。
- 幂等操作:如果请求对应的操作是幂等的,即多次重复请求会产生相同的结果,可以考虑使用GET方法。
总的来说,需要根据具体的业务需求和安全考虑来选择是使用GET还是POST方法。
02、表单元素
表单元素****单标签、行内元素,主要用于输入各种类型数据。包含多个表单类型type
:文本框、复选框、单选框、按钮等。
input.type
input.type/ 属性 | 描述 | 备注 |
---|---|---|
text | 文本输入框(默认),单行文本,不支持换行 | <input type="text"> |
password | 密码输入框 | |
radio | 单选框,相同name为一组互斥 | 记得赋值value |
checkbox | 多选框,相同name为一组。如选中多个值会提交多个key-value | 记得赋值value |
number | 数字输入,step 设置步长 | |
hidden | 隐藏框/域,页面不可见,用于一些逻辑处理 | |
button | 普通按钮,按钮显示value 值,结合JavaScript事件使用 <input type="button" value="提交" onclick=""> | 建议用<button> 元素代替 |
submit | 表单提交按钮,在form中有效,直接提交表单数据 | 同<button> 元素的submit 模式 |
reset | 表单重置按钮,重置表单的数据,form中有效。 | |
image | 图片提交按钮,同submit,src 设置图片,无图则显示alt | height、width设置图片大小 |
file | 文件选择框,如多值则value为第一个值,js获取files取多个值 | capture媒体拍摄方式-移动端 |
accept | 可接受文件类型,多个逗号隔开,image/png, video/* | .jpg,.png,.doc |
电子邮箱,支持邮箱格式验证 | 验证邮箱格式 | |
range | 滑块数字,用 min 和 max 来设置值的范围,step设置步长 | list 可设置刻度 |
search | 搜索框,和text 差不多 | |
tel | 电话号码,和text 差不多,有些终端支持虚拟键盘 | 不验证(不同地区格式不同) |
url | URL地址,和text 差不多 | 验证url格式 |
color,IE🚫 | 颜色输入控件, | |
date,IE🚫 | 日期输入,年月日 | |
datetime-local,IE🚫 | 日期时间输入,年月日、时分秒,Chrome/Opera /Edge支持 | yyyy-MM-ddThh:mm |
month,IE🚫 | 年月输入,输入年份或月份 | value="2018-05" |
time,IE🚫 | 时间控件,小时、分 | |
week,IE🚫 | 年和周数,用于输入以年和周数组成的日期,支持的不多 |
📢注意:
- 一般浏览器对不支持的type,都默认降级为text。
- 文件选择框如通过表单提交,表单需设置属性
enctype="multipart/form-data"
设置表单数据编码为多种数据组合,同时设置提交方式为post,才可以上传文件(二进制)。
的常规属性
基础属性 | 描述 | 相关type | 值/备注 |
---|---|---|---|
name | 控件名称(通用属性),表单中须赋值,会作为参数名 | ||
type | 表单控件类型 | 详见上表 | |
value | <input> 的值,可设置默认值。 | ||
tabindex | 当前文档的 Tab 导航顺序中的位置 | ||
size | 宽度,文本框可显示的字符宽度,类似css的width | 字符数量 | |
min/maxlength | 可输入字符数量,文本框可输入最少/大字符数量 | 文本输入类 | |
readonly | 只读,不可编辑,IE有光标显示 | true 值可省略 | |
disabled | 不可用,无光标 | 值可省略 | |
placeholder | 占位符/水印,用于输入提示,比较常用 | 文本输入类 | |
checked | 选中状态 | 单选、多选 | 值可省略 |
min/max | 最大/小值,数字、日期值的边界 | 数字、日期 | 大小边界验证 |
pattern,IE10 | 模式(正则表达式),用于值的合法性检测 | 文本输入类 | 正则验证 |
required | 必填,hidden、image 或者按钮类型无效 | 值可省略,必填验证 | |
multiple | 是否允许多个值,逗号隔开 | email、file | 布尔值,值可省略 |
step | 步长,数字、日期 | 数字、日期 | |
list | 候选值:输入框的候选值列表,值,显示value | 大多数 | |
autocomplete | 自动填充,设置浏览器的自动填充模式 | 大多数 | |
autofocus | 页面加载时自动聚焦 | 布尔值,值可省略 | |
inputmode | 值输入模式,虚拟键盘,text, tel, url, email, numeric | 文本输入类 | |
form | 所属form,值为其id | ||
formaction | 表单提交属性,还有formenctype、formmethod、formnovalidate、formtarget | image、submit |
<style>
.iform {
text-align: right;
display: grid;
grid-template-columns: 80px 200px 80px 200px;
gap: 10px 5px;
}
/* 重写radio的样式 */
.iform input[type="radio"] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border-radius: 50%;
width: 20px;
height: 20px;
border: 3px solid #999;
transition: 0.2s all linear;
outline: none;
position: relative;
}
.iform input[type="radio"]:checked {
border: 6px solid #4A80FF;
}
.iform input:invalid {
border-color: red;
}
.iform input,.iform label {
height: 26px;
padding: 0 3px;
display: inline-block;
vertical-align: middle;
}
</style>
<form class="iform">
text:<input type="text" autocomplete="on" required placeholder="username" autofocus>
password:<input type="password" required maxlength="12" minlength="6">
number:<input type="number" step="12" min="1" value="33" >
radio:<div style="text-align:left;">
<label><input type="radio" name="sex" checked>男</label>
<label><input type="radio" name="sex">女</label></div>
checkbox:<div style="text-align:left;">
<label><input type="checkbox" name="cbgroup">做饭</label>
<label><input type="checkbox" name="cbgroup">打球</label></div>
<input type="hidden" value="key123">
file:<input type="file" accept="image/*">
email:<input type="email" inputmode="email" pattern=".+@163.com" placeholder="***@163.com">
range:<input type="range" min="0" max="100" value="10" step="5">
search:<input type="search" list="slist">
tel:<input type="tel" pattern="[0-9]*" maxlength="14">
url:<input type="url" placeholder="http://example.com">
color:<input type="color" value="#ff0000" >
datetime-local<input type="datetime-local">
month:<input type="month" step="1">
time:<input type="time" value="12:12">
week:<input type="week" value="12:12" required>
<input type="reset" value="reset重置">
<input type="button" value="普通按钮">
<input type="image" src="../res/btnb.png" width="60px">
<input type="submit" value="submit提交">
</form>
数据集合
****数据集合元素,包含了一组<option>
元素,提供给文本类<input>
(list
属性)使用,作为可选值的数据集。
- 文本、数字输入的候选值,包括text、number、email、url、tel、search等。
range
的刻度。
<datalist id="optfruit">
<option value="香蕉">香蕉</option>
<option value="火龙果">火龙果</option>
<option value="绿色蔬菜">冬瓜</option>
<option value="男瓜">
<option value="其他">
</datalist>
<input type="search" list="optfruit">
03、多行文本
**** 可以输入多行文本,支持换行、空格,行内元素。
属性 | 描述 | 值 |
---|---|---|
name | 表单提交数据的key | |
rows | 文本行数,同css样式的高度 | 整数 |
cols | 文本列数,同css样式的宽度 | 整数 |
<textarea>
还可以使用<input>
中的一些常见属性,如autocomplete、autofocus、disabled、placeholder、readonly,和 required、maxlength等。可使用css样式属性resize
设置输入框的大小调整方式。
<p>
<label for="txtsumary">个人简介:</label>
<textarea name="txtsumary" rows="3" cols="50" style="resize: vertical;" required>多行文本内容,
支持空格、换行</textarea>
</p>
04、
****是一个文本标签,最主要的使命是辅助表单元素聚焦,点击
属性 | 描述 |
---|---|
for | 关联的元素id |
form | <form> 的id,可以将<label> 放到form外面了,这就很自由了! |
<p>
<label for="uname">
<span>Name:</span>
<input id="uname" type="text" name="uname">
<span title="required">*</span>
</label>
</p>
<div>
<label for="username">Name: <span title="required">*</span></label>
<input id="username" type="text" name="username">
</div>
<label>
<input type="checkbox" />阅读并同意条款<img src="../res/head-48.gif" width="24px">
</label>
⭐还有一种简写的方式:用 label 元素把 input 元素包裹起来,以减少for- id 的使用。
05、按钮
<*button*> 是HTML5的新元素,行内元素,作用和input-button
的功能基本相同。不同的是他是双标签
,内部可以自由定义内容,也可以使用伪元素,实现更丰富的按钮效果,所以按钮用他就对了。
属性 | 描述 | 值 |
---|---|---|
type | 按钮的类型 | button:普通按钮;submit:表单提交按钮;reset:表单重置按钮; |
value | button 的初始值,参数的形式随表单提交 |
<button type="button">普通按钮</button>
<button type="submit">提交submit</button>
<button type="reset" style="width:80px;"><img src="../res/sk (13).png"><br/>重置</button>
<button>
和<input button>
的区别?
<input>
是单标签,无关闭标签。<button>
的显示内容在标签之间,应用场景更丰富;<input>
的显示内容在value
属性上,只支持纯文本。<button>
的鼠标事件里可以直接写代码。
06、<select/option>选项
<select>
选择列表元素,行内元素,有弹出下拉框、选项列表两种模式,<option>
是他的选项子元素。启用multiple
或size>1
时,显示为列表,否则显示为下拉框模式。
元素/属性 | 描述 | 值/备注 |
---|---|---|
**** | 选项控件 | |
required | 必填,表单的通用属性,还有disabled、autofocus、form等 | |
multiple | 多选,显示为列表,不设置该属性则弹出下拉框。 | 值也是multiple,值可省略 |
size | 控件显示的选项行数,配合multiple使用 | 整数,默认1 |
value/selectedIndex | 选中的值/索引 | |
**** | <select> 的选项子元素 | |
selected | 设置选中 | 值可省略 |
value | 选项的值 | 如果没有value,则取标签内容 |
disabled | 不可用 | |
**** | 选项分组,给<option> 分组 | |
label | 显示的文本 | |
disabled | 分组都禁用 |
html复制代码<form action="">
多选multiple:
<select id="selfruit" name="selfruit" multiple size="4" list="optfruit">
<optgroup label="热带水果">
<option value="1">香蕉</option>
<option value="2">火龙果</option>
</optgroup>
<optgroup label="蔬菜">
<option value="3">绿色蔬菜</option>
<option value="4">冬瓜</option>
<option value="4" disabled>男瓜</option>
</optgroup>
<option value="5">其他</option>
</select>
单选:
<select name="selsex" size="0" required>
<option value="" selected>选择性别</option>
<option value="1">男</option>
<option value="2">女</option>
<option value="5">其他</option>
</select>
<input type="submit">
</form>
07、进度计量
两者都可以实现进度的效果,<progress>
为进度条元素。<meter>
更为丰富,表示某种计量,适用于温度、重量、金额等量化的可视化展示。
属性 | 描述 |
---|---|
****IE10 | 进度条 |
max | 最大值,默认为1 |
value | 进度值,不设置则为"不确定"状态,显示为加载中的效果(不同浏览器表现不同) |
****IE🚫 | 进度计量,显示已知范围的标量值或者分数值。(/ˈmiːtər/ 计量) |
value | 值 |
min/max | 最小值(默认0),最大值(默认1) |
low/high | 低值、高值,用于设置“正常值”的边界区域,以显示不同效果 |
optimum | 最优值( /ˈɑːptɪməm/ ),配合low/high使用,判断当前值是否最优 |
form | 关联form表单的id |
<fieldset style="display:inline-block;">
<legend>Progress</legend>
progress:<progress value="0.3"></progress><br>
progress(无value): <progress></progress><br>
value溢出: <progress max="100" value="120"></progress>
</fieldset>
<fieldset style="display:inline-block;">
<legend>Meter</legend>
普通进度:<meter value="0.2"></meter><br>
value小于low:<meter value="10" max="60" min="0" optimum="26" low="20" high="30"></meter><br>
value大于high:<meter value="55" max="60" min="0" optimum="15" low="20" high="30"></meter><br>
value居中<meter value="25" max="60" min="0" optimum="26" low="20" high="30"></meter>
</fieldset>
08、表单布局
表单是前端常用的组件,布局必不可少,一个美观、简介的布局尤为重要。一个最小单位的表单输入部件,除了表单元素,还必须考虑标题、错误提示等。对于整个表单还要考虑多个表单输入项的行列排列、对齐。
最基本的HTML表单布局思路:
- 小部件:用
<div>
或<p>
包装一个最小的部件,里面包含<label>
表单项标题、<input>
、<span>
提示信息。
<div>
<label for="uname">姓名:</label> <!-- 标签 -->
<input type="text" name="uname" required maxlength="20"> <!-- 表单元素 -->
<span title="必填">*</span> <!-- 作为额外提示,包括输入验证错误的提示信息 -->
</div>
- 表单分区,对于复杂的表单,用
<fieldset>
、标题<h*>
、分段<section>
等来分区组织不同类型的内容。 - 表单布局:借助CSS表格布局、Grid、Flex等工具进行布局。
- 第三方表
【二】Form组件校验数据
【1】前言
- 手动书写前端获取用户数据的html代码 渲染html代码
- 后端对用户数据进行校验 校验数据
- 对不符合要求的数据进行前端提示 展示提示信息
【2】form组件
-
能够完成的事情
- 渲染html代码
- 校验数据
- 展示提示信息
-
为什么数据校验要在后端执行,而不是前端在JS完成?
- 数据校验前端可有可无
- 但是后端必须有!
-
原因
- 前端的校验存在实时被修改的风险,可以在前端直接修改输入的数据
- 利用爬虫程序可以绕过前端页面直接向后端提交数据
-
例如购物网站
- 在前端计算完总价后,直接提交给后端
- 后端如果不做校验就会产生极大的风险安全问题
- 正确的做法是
- 在后端查出所有商品的必要信息,再次计算一遍
- 前段与后端都要进行校验,保证数据的安全性
小结:
当涉及到用户数据的校验时,通常建议在后端执行数据校验,而不是仅依赖前端的JavaScript校验。以下是原因和正确的做法:
- 前端校验存在风险:前端校验是在用户的浏览器上进行的,用户可以通过修改JavaScript代码或使用其他工具绕过前端校验。这样就无法保证数据的完整性和安全性。
- 防止绕过前端:通过爬虫程序或其他方式,用户可以直接向后端提交数据,绕过前端页面的校验。如果只依赖前端校验,后端将无法有效地防止非法或不符合要求的数据进入系统。
在表单中进行数据验证是确保用户输入的数据符合特定要求的重要步骤。在前端开发中,可以使用各种方法和工具来验证表单数据。下面是一些常见的前端验证方法:
-
HTML5表单验证:HTML5提供了一些内置的表单验证属性和方法,例如
required
、pattern
、min
、max
等。可以通过在表单元素上添加这些属性来实现基本的数据验证。(推荐使用) -
JavaScript验证:使用JavaScript编写自定义的验证逻辑。可以通过在表单的提交事件中编写验证函数,对表单数据进行检查并给出相应的提示或错误信息。(太过琐碎)
-
第三方验证库:使用第三方的JavaScript验证库,例如jQuery Validation、VeeValidate、Formik等。这些库提供了更强大和灵活的验证功能,可以处理复杂的验证需求,并提供更好的用户体验。
【3】示例
<form>
<label for="name">姓名:</label>
<input type="text" id="name" required>
<label for="email">邮箱:</label>
<input type="email" id="email" required>
<button type="submit">提交</button>
</form>
<script>
const form = document.querySelector('form');
form.addEventListener('submit', function(event) {
event.preventDefault(); // 阻止表单的默认提交行为
// 获取表单元素的值
const name = document.getElementById('name').value;
const email = document.getElementById('email').value;
// 执行验证逻辑
if (name === '') {
alert('请输入姓名');
return;
}
if (email === '') {
alert('请输入邮箱');
return;
}
// 数据验证通过,可以进行表单提交或其他操作
alert('表单验证通过,可以进行提交');
// form.submit(); // 提交表单
});
</script>
required
属性用于指定必填字段,如果用户没有填写相应的字段,浏览器会给出相应的提示。JavaScript部分通过监听表单的提交事件,获取表单元素的值,并进行自定义的验证逻辑。如果验证不通过,会给出相应的提示信息。
form表单
# urls.py
from apply03 import views
urlpatterns = [
path('ti_form/',views.ti_form),
]
# views.py
from django.shortcuts import render
def ti_form(request):
form_dict = {'username':'','password':''}
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if '你死了' in username:
form_dict['username'] = '请文明用语!!!'
if len(password) < 4:
form_dict['password'] = '密码过于简单!!!'
return render(request, 'ti_form.html', locals())
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load static %}
<script src="{% static 'js/jquery-3.5.1.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<form action="" method="post">
<p>username:
<input type="text" name="username">
<span style="color: blue">{{ form_dict.username }}</span>
</p>
<p>password:
<input type="text" name="password">
<span style="color: blue">{{ form_dict.password }}</span>
</p>
<input type="submit" class="btn btn-info">
</form>
</body>
</html>
【4】前后端交互流程:
【三】Django中的form所有内置字段
Field
required=True, 是否允许为空
widget=None, HTML插件
label=None, 用于生成Label标签或显示内容
initial=None, 初始值
help_text='', 帮助信息(在标签旁边显示)
error_messages=None, 错误信息 {'required': '不能为空', 'invalid': '格式错误'}
validators=[], 自定义验证规则
localize=False, 是否支持本地化
disabled=False, 是否可以编辑
label_suffix=None Label内容后缀
CharField(Field)
max_length=None, 最大长度
min_length=None, 最小长度
strip=True 是否移除用户输入空白
IntegerField(Field)
max_value=None, 最大值
min_value=None, 最小值
FloatField(IntegerField)
...
DecimalField(IntegerField)
max_value=None, 最大值
min_value=None, 最小值
max_digits=None, 总长度
decimal_places=None, 小数位长度
BaseTemporalField(Field)
input_formats=None 时间格式化
DateField(BaseTemporalField) 格式:2015-09-01
TimeField(BaseTemporalField) 格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
DurationField(Field) 时间间隔:%d %H:%M:%S.%f
...
RegexField(CharField)
regex, 自定制正则表达式
max_length=None, 最大长度
min_length=None, 最小长度
error_message=None, 忽略,错误信息使用 error_messages={'invalid': '...'}
EmailField(CharField)
...
FileField(Field)
allow_empty_file=False 是否允许空文件
ImageField(FileField)
...
注:需要PIL模块,pip3 install Pillow
以上两个字典使用时,需要注意两点:
- form表单中 enctype="multipart/form-data"
- view函数中 obj = MyForm(request.POST, request.FILES)
URLField(Field)
...
BooleanField(Field)
...
NullBooleanField(BooleanField)
...
ChoiceField(Field)
...
choices=(), 选项,如:choices = ((0,'上海'),(1,'北京'),)
required=True, 是否必填
widget=None, 插件,默认select插件
label=None, Label内容
initial=None, 初始值
help_text='', 帮助提示
ModelChoiceField(ChoiceField)
... django.forms.models.ModelChoiceField
queryset, # 查询数据库中的数据
empty_label="---------", # 默认空显示内容
to_field_name=None, # HTML中value的值对应的字段
limit_choices_to=None # ModelForm中对queryset二次筛选
ModelMultipleChoiceField(ModelChoiceField)
... django.forms.models.ModelMultipleChoiceField
TypedChoiceField(ChoiceField)
coerce = lambda val: val 对选中的值进行一次转换
empty_value= '' 空值的默认值
MultipleChoiceField(ChoiceField)
...
TypedMultipleChoiceField(MultipleChoiceField)
coerce = lambda val: val 对选中的每一个值进行一次转换
empty_value= '' 空值的默认值
ComboField(Field)
fields=() 使用多个验证,如下:即验证最大长度20,又验证邮箱格式
fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
MultiValueField(Field)
PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
SplitDateTimeField(MultiValueField)
input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹
required=True,
widget=None,
label=None,
initial=None,
help_text=''
GenericIPAddressField
protocol='both', both,ipv4,ipv6支持的IP格式
unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
SlugField(CharField) 数字,字母,下划线,减号(连字符)
...
UUIDField(CharField) uuid类型
【四】Form组件如何校验数据
校验数据一般是在python Console
Python控制台中实现的
先定义一个表如:
from django import forms
class MyForm(forms.Form):
# username字符串类型最小4位最大12位
username = forms.CharField(min_length=4,max_length=12)
# password字符串类型最小4为最大12位
password = forms.CharField(min_length=4,max_length=12)
# email 字段必须符合邮箱格式 xxxx@xx.com
email = forms.EmailField()
【1】在验证的时候可能会发生的错误
Traceback (most recent call last):
File "D:\pycharm\PyCharm 2023.2.1\plugins\python\helpers\pydev\pydevconsole.py", line 364, in runcode
coro = func()
^^^^^^
File "<input>", line 6, in <module>
File "F:\pthon\python311\Lib\site-packages\django\__init__.py", line 19, in setup
configure_logging(settings.LOGGING_CONFIG, settings.LOGGING)
^^^^^^^^^^^^^^^^^^^^^^^
File "F:\pthon\python311\Lib\site-packages\django\conf\__init__.py", line 89, in __getattr__
self._setup(name)
File "F:\pthon\python311\Lib\site-packages\django\conf\__init__.py", line 69, in _setup
raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: Requested setting LOGGING_CONFIG, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
【2】解决方法
方法一:
在python Console 中 写下
settings.configure()
方法****
import os
from django.conf import settings
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Books.settings')
settings.configure()
方法二:
设置DJANGO_SETTINGS_MODULE
环境变量:在你的代码中添加以下行,设置DJANGO_SETTINGS_MODULE
环境变量为你的Django项目的设置模块路径:
就是在主项目中settings.py文件中
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Books.settings')
还是没用就先在根目录创建一个文件夹userForm
在这个文件夹下面创建一个py文件。
第一步:
- 导入
forms
模块
from django import forms
第二步:
- 创建一个表确保这个表最好跟前后端要保持一致。
# 后端 在userForm文件夹下的py文件
# 按照Django form组件的要求自己写一个类 Form
class Form(forms.Form):
# username : 字符串类型 最小4位,最大12位
username = forms.CharField(max_length=12, min_length=4)
# # password : 字符串类型 最小4位,最大12位
password = forms.CharField(max_length=12, min_length=4)
# email : 必须符合邮箱格式 xxx@xx.com
email = forms.EmailField()
# 在应用程序的views.py
from django.shortcuts import render
def ti_form(request):
form_dict = {'username':'','password':'','email':''}
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
email = request.POST.get('email')
if '你死了' in username:
form_dict['username'] = '请文明用语!!!'
if len(password) < 4:
form_dict['password'] = '密码过于简单!!!'
if len(email) < 4:
form_dict['email'] = '你是个傻子没跑了!!!'
return render(request, 'ti_form.html', locals())
# 前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load static %}
<script src="{% static 'js/jquery-3.5.1.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<form action="" method="post">
<p>username:
<input type="text" name="username">
<span style="color: blue">{{ form_dict.username }}</span>
</p>
<p>password:
<input type="password" name="password">
<span style="color: blue">{{ form_dict.password }}</span>
</p>
<p>eamil:
<input type="password" name="email">
<span style="color: blue">{{ form_dict.email }}</span>
</p>
<input type="submit" class="btn btn-info">
</form>
</body>
</html>
第三步:
- 测试环境准备
import os
import django
if __name__ == '__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Books.settings')
django.setup()
#创建一个对象
res = Form(
{"username": "dream", "password": "521", "eemail": "123"}
)
print(res)
【3】测试方法
from django import forms
# 按照Django form组件的要求自己写一个类 Form
class Form(forms.Form):
# username : 字符串类型 最小4位,最大12位
username = forms.CharField(max_length=12, min_length=4)
# # password : 字符串类型 最小4位,最大12位
password = forms.CharField(max_length=12, min_length=4)
# email : 必须符合邮箱格式 xxx@xx.com
email = forms.EmailField()
import os
import django
if __name__ == '__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Books.settings')
django.setup()
res = Form(
{"username": "jiasndgasd", "password": "454545", "email": "123"}
)
print(res.is_valid())
# False
print(res.changed_data)
# ['username', 'password', 'email']
print(res.errors)
# <ul class="errorlist"><li>email<ul class="errorlist"><li>Enter a valid email address.</li></ul></li></ul>
res1 = Form(
{"username": "jiangyi",
"password": "12121",
"email": "123@qq.com",
"hobby": "music"}
)
print(res1.is_valid())
# True
res2 = Form({"username": "jingyi", "password": "12121"})
print(res2.errors)
# li>email<ul class="errorlist"><li>This field is required.(此字段为必填项)</li>
- 默认情况下
- 校验数据可以多传
- 但是不能少传
from django import forms
# 按照Django form组件的要求自己写一个类 Form
class Form(forms.Form):
# username : 字符串类型 最小4位,最大12位
username = forms.CharField(max_length=12, min_length=4)
# # password : 字符串类型 最小4位,最大12位
password = forms.CharField(max_length=12, min_length=4)
# email : 必须符合邮箱格式 xxx@xx.com
email = forms.EmailField()
import os
import django
if __name__ == '__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Books.settings')
django.setup()
res = Form(
{"username": "jiasndgasd", "password": "454545", "email": "123"}
)
# 数据是否合法(is_valid)
print(res.is_valid())
# False
# 查看合法数据(changed_data)
print(res.changed_data)
# ['username', 'password', 'email']
# 查看不合法的数据(errors)
print(res.errors)
# <ul class="errorlist"><li>email<ul class="errorlist"><li>Enter a valid email address.</li></ul></li></ul>
# 多传参数是否会报错
res1 = Form(
{"username": "jiangyi",
"password": "12121",
"email": "123@qq.com",
"hobby": "music"}
)
print(res1.is_valid())
# True
# 少传参数是否会报错
res2 = Form({"username": "jingyi", "password": "12121"})
print(res2.errors)
# li>email<ul class="errorlist"><li>
# This field is required.(此字段为必填项)</li>
总结:
- 校验数据可以多传字段,但不能少传字段。
- 合法数据可以通过
changed_data
属性获取。 - 不合法数据和对应的错误信息可以通过
errors
属性获取。
【4】渲染标签
- forms组件只会自动帮你渲染获取用户输入的标签(input | select | radio | checkbox)
- label属性默认展示的是类中定义的字段首字母大写形式,也可以自己修改,直接给字段对象label属性即可。
使用方法
- 先产生一个空的对象
#views.py文件
from django.shortcuts import render
# 导入userForm文件
from Form.userForm import Form
def index(request):
# 1.先产生一个空对象
form = Form()
# 2.直接将空对象传递给html页面
return render(request,'index1.html',locals())
- 直接将空对象传递给html页面
return render(request,'index1.html',locals())
- 前端利用看对象操作
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load static %}
<title>Title</title>
<script src="{% static 'js/jquery-3.5.1.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<form action="" method="post" ></form>
{# <p>第一种渲染方法</p>#}
{# <!-- {{ form.as_p }} --> #}
{# <!-- {{ form.as_ul }} --> #}
{# <!-- {{ form.as_table }} --> #}
{# <p>第二种渲染方法</p>#}
{# <p>{{ form.username.label }}{{ form.username }}</p>#}
{# <p>{{ form.password.label }}{{ form.password }}</p>#}
{# <p>{{ form.email.label }}{{ form.email }}</p>#}
<p>第三种渲染方法</p>
{% for f in form %}
<P>{{ f.label }}:{{ f }}</P>
{% endfor %}
</body>
</html>
【1】第一种渲染方法
- 代码书写极少,封装程度太高,不便于后续的扩展,一般情况下只在本地测试使用。
<!-- {{ form.as_p }} -->
<!-- {{ form.as_ul }} -->
<!-- {{ form.as_table }} -->
【2】第二种渲染方法
-
这种方法可扩展性很强,但是需要书写的代码太多,一般情况下不用!!
-
在Form文件夹中的userForm.py文件
-
可以编辑页面
-
from django import forms
# 按照Django form组件的要求自己写一个类 Form
class Form(forms.Form):
# username : 字符串类型 最小4位,最大12位
username = forms.CharField(max_length=12, min_length=4, label='用户名!')
# # password : 字符串类型 最小4位,最大12位
password = forms.CharField(max_length=12, min_length=4, label='密码!')
# email : 必须符合邮箱格式 xxx@xx.com
email = forms.EmailField(label='邮箱!')
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load static %}
<title>Title</title>
<script src="{% static 'js/jquery-3.5.1.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<form action="" method="post" ></form>
这种方法可扩展性很强,但是需要书写的代码太多
<p>第二种渲染方法</p>
<p>{{ form.username.label }}{{ form.username }}</p>
<p>{{ form.password.label }}{{ form.password }}</p>
<p>{{ form.email.label }}{{ form.email }}</p>
</body>
</html>
【3】第三种渲染方法
-
推荐使用:代码书写简单,并且扩展性很高!
-
from django import forms # 按照Django form组件的要求自己写一个类 Form class Form(forms.Form): # username : 字符串类型 最小4位,最大12位 username = forms.CharField(max_length=12, min_length=4, label='用户名!') # # password : 字符串类型 最小4位,最大12位 password = forms.CharField(max_length=12, min_length=4, label='密码!') # email : 必须符合邮箱格式 xxx@xx.com email = forms.EmailField(label='邮箱!')
import os import django if __name__ == '__main__': os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Books.settings') django.setup() res = Form( {"username": "jiasndgasd", "password": "454545", "email": "123"} ) # 数据是否合法(is_valid) print(res.is_valid()) # False # 查看合法数据(changed_data) print(res.changed_data) # ['username', 'password', 'email'] # 查看不合法的数据(errors) print(res.errors) # <ul class="errorlist"><li>email<ul class="errorlist"><li>Enter a valid email address.</li></ul></li></ul> # 多传参数是否会报错 res1 = Form( {"username": "jiangyi", "password": "12121", "email": "123@qq.com", "hobby": "music"} ) print(res1.is_valid()) # True # 少传参数是否会报错 res2 = Form({"username": "jingyi", "password": "12121"}) print(res2.errors) # li>email<ul class="errorlist"><li> # This field is required.(此字段为必填项)</li>
这个是测试方法
<p>第三种渲染方法</p>
<!-- form = Form() 这个就是你在你定义Form文件夹中定义的userForm文件。这里定义的就是ORM数据的数据
f == form.username
f.label == form.username.label -->
{% for f in form %}
<P>{{ f.label }}:{{ f }}</P>
{% endfor %}
【4】总结
- 第一种渲染方法:
- 代码书写极少,封装程度高,适用于本地测试使用。
- 可以使用
{{ form.as_p }}
、{{ form.as_ul }}
或{{ form.as_table }}
来渲染表单字段。
- 第二种渲染方法:
- 可扩展性强,但需要编写较多的代码,一般情况下不常使用。
- 在模板中使用
{{ form.field.label }}{{ form.field }}
的形式来渲染表单字段。
- 第三种渲染方法:
- 推荐使用,代码书写简单且具有较高的扩展性。
- 在模板中使用
{% for field in form %}{{ field.label }}:{{ field }}{% endfor %}
的形式来渲染表单字段。
这些渲染方法可以根据你的需求选择使用。第一种方法简单快捷,适用于简单的表单场景;第二种方法需要手动编写每个字段的渲染代码,适用于对表单样式有特殊要求的场景;第三种方法是推荐的方法,代码简洁且具有较高的灵活性。
用form表单提交数据
用FORM表单写一个登陆注册功能
from django.contrib import admin
from django.urls import path
from login import views
# app_name = 'user'
urlpatterns = [
path('admin/', admin.site.urls),
# 登陆
path('login/', views.login, name='login'),
# 注册
path('register/', views.register, name='register'),
]
# views.py
from django.shortcuts import render,redirect,HttpResponse
from login import models
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
# 取User表中username,password的数据
user = models.User.objects.filter(username=username,password=password).exists()
if user:
return render(request,'1.html')
else:
return render(request,'login.html',{'error_message': 'Invalid username or password'})
return render(request,'login.html')
def register(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
# 用户数据保持在数据库当中。
new_user = models.User(username=username,password=password)
new_user .save()
return render(request,'1.html')
return render(request,'register.html')
<div>注册页面</div>
<h2>Register</h2>
<form method="post">
{% csrf_token %}
<label for="username">Username:</label>
<input type="text" name="username" id="username"><br><br>
<label for="password">Password:</label>
<input type="password" name="password" id="password"><br><br>
<button type="submit">Register</button>
</form>
------------------------------------------------------------
<div>登陆页面</div>
<h2>Login</h2>
<form action="{% url 'login' %}" method="post">
<label for="username">账号:</label><br>
<input type="text" id="username" name="username"><br>
<label for="password">密码:</label><br>
<input type="password" id="password" name="password"><br><br>
<input type="submit" value="Login">
</form>
:
return render(request,‘1.html’)
else:
return render(request,‘login.html’,{‘error_message’: ‘Invalid username or password’})
return render(request,‘login.html’)
def register(request):
if request.method == ‘POST’:
username = request.POST.get(‘username’)
password = request.POST.get(‘password’)
# 用户数据保持在数据库当中。
new_user = models.User(username=username,password=password)
new_user .save()
return render(request,'1.html')
return render(request,'register.html')
```html
<div>注册页面</div>
<h2>Register</h2>
<form method="post">
{% csrf_token %}
<label for="username">Username:</label>
<input type="text" name="username" id="username"><br><br>
<label for="password">Password:</label>
<input type="password" name="password" id="password"><br><br>
<button type="submit">Register</button>
</form>
------------------------------------------------------------
<div>登陆页面</div>
<h2>Login</h2>
<form action="{% url 'login' %}" method="post">
<label for="username">账号:</label><br>
<input type="text" id="username" name="username"><br>
<label for="password">密码:</label><br>
<input type="password" id="password" name="password"><br><br>
<input type="submit" value="Login">
</form>