Django之form组件自动校验数据实现


Posted in Python onJanuary 14, 2020

一、form介绍

我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来。

与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否输入,输入的长度和格式等正不正确。如果用户输入的内容有错误就需要在页面上相应的位置显示对应的错误信息.。

Django form组件就实现了上面所述的功能。

总结一下,其实form组件的主要功能如下:

  • 生成页面可用的HTML标签
  •  对用户提交的数据进行校验
  • 保留上次输入内容

二、普通方式手写注册功能

views.py

# 注册
def register(request):
  error_msg = ""
  if request.method == "POST":
    username = request.POST.get("name")
    pwd = request.POST.get("pwd")
    # 对注册信息做校验
    if len(username) < 6:
      # 用户长度小于6位
      error_msg = "用户名长度不能小于6位"
    else:
      # 将用户名和密码存到数据库
      return HttpResponse("注册成功")
  return render(request, "register.html", {"error_msg": error_msg})

register.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>注册页面</title>
</head>
<body>
<form action="/reg/" method="post">
  {% csrf_token %}
  <p>
    用户名:
    <input type="text" name="name">
  </p>
  <p>
    密码:
    <input type="password" name="pwd">
  </p>
  <p>
    <input type="submit" value="注册">
    <p style="color: red">{{ error_msg }}</p>
  </p>
</form>
</body>
</html>

三、使用form组件实现注册功能

views.py

先定义好一个RegForm类:

from django import forms

# 按照Django form组件的要求自己写一个类
class RegForm(forms.Form):
  name = forms.CharField(label="用户名")
  pwd = forms.CharField(label="密码")

再写一个视图函数:

# 使用form组件实现注册方式
def register2(request):
  form_obj = RegForm()
  if request.method == "POST":
    # 实例化form对象的时候,把post提交过来的数据直接传进去
    form_obj = RegForm(request.POST)
    # 调用form_obj校验数据的方法
    if form_obj.is_valid():
      return HttpResponse("注册成功")
  return render(request, "register2.html", {"form_obj": form_obj})

register2.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>注册2</title>
</head>
<body>
  <form action="/reg2/" method="post" novalidate autocomplete="off">
    {% csrf_token %}
    <div>
      <label for="{{ form_obj.name.id_for_label }}">{{ form_obj.name.label }}</label>
      {{ form_obj.name }} {{ form_obj.name.errors.0 }}
    </div>
    <div>
      <label for="{{ form_obj.pwd.id_for_label }}">{{ form_obj.pwd.label }}</label>
      {{ form_obj.pwd }} {{ form_obj.pwd.errors.0 }}
    </div>
    <div>
      <input type="submit" class="btn btn-success" value="注册">
    </div>
  </form>
</body>
</html>

看网页效果发现 也验证了form的功能:

  • 前端页面是form类的对象生成的 -->生成HTML标签功能
  • 当用户名和密码输入为空或输错之后 页面都会提示 -->用户提交校验功能
  • 当用户输错之后 再次输入 上次的内容还保留在input框 -->保留上次输入内容

四、pycharm的专属测试环境

1.使用方法

1.导入要测试的py文件

2.生成一个对象

Django之form组件自动校验数据实现

Django之form组件自动校验数据实现

2.本地校验测试的一些参数

from_obj.is_valid()     //判断校验是否通过
from_obj.cleaned_data    //拿到当前符号校验的数据{'username': '111', 'password': '111'}
form_obj.errors       //拿到当前校验不通过的数据

少传参数Flalse,多传Trun。因为少传了拿不到校验的数据,多传了也不会使用。这是字典的形式

五、html自动生成input用户输入框的三种方式

forms组件只帮你渲染获取用户输入(输入 选择 下拉 文件)的标签 不渲染按钮和form表单标签

渲染出来的每一个input提示信息都是类中字段首字母大写

class MyRegForm(forms.Form):
  username = forms.CharField(max_length=8, min_length=3) # 最长8位,最短3位
  password = forms.CharField(max_length=8, min_length=3) # 最长8位,最短3位
  email = forms.EmailField() # 邮箱验证
  
def reg(request):
  # 1 先生成一个空的类对象
  form_obj = MyRegForm()
  if request.method == 'POST':
    # 3 获取用户数据并交给forms组件校验 request.POST
    form_obj = MyRegForm(request.POST)
    # 4 获取校验结果
    if form_obj.is_valid():
      return HttpResponse('数据没问题')
    else:
      # 5 获取校验失败的字段和提示信息
      print(form_obj.errors)
  # 2 直接将该对象传给前端页面
  return render(request, 'reg.html', locals())

第一种方式 {{ form_obj.as_p }} (不推荐)

不推荐,封装程度高,扩展性低。一般测试本地用

<body>
<p>第一种渲染方式:多个p标签 本地测试方便 封装程度太高了 不便于扩展</p>
{{ form_obj.as_p }}
{#{{ form_obj.as_ul }}#}
{#{{ form_obj.as_table }}#}
</body>

Django之form组件自动校验数据实现

第二种方式 {{ form_obj.username }} (不推荐)

不推荐,扩展性较高 ,书写较为繁琐,每一个input框都需要自己手动写

<p>第二种渲染方式: 扩展性较高 书写较为繁琐</p>
<label for="{{ form_obj.username.id_for_label }}">{{ form_obj.username.label }}</label>
{{ form_obj.username }}
{{ form_obj.password.label }}{{ form_obj.password }}
{{ form_obj.email.label }}{{ form_obj.email }}

Django之form组件自动校验数据实现

第三种方式 for循环 (推荐)

推荐使用,for循环方式

{{ form.errors.0 }} # 这个是模板语法

<p>第三种渲染方式 推荐使用</p>
<form action="" method="post" novalidate>
  {% for form in form_obj %}
  <p>
    {{ form.label }}{{ form }}
    <span>{{ form.errors.0 }}</span>
  </p>
  {% endfor %}
  <input type="submit">
</form>

Django之form组件自动校验数据实现

Django之form组件自动校验数据实现

六、数据校验

*******数据校验一个前后端都得有 但是前端的校验弱不禁风 可有可无

而后端的校验则必须非常全面

如何取消浏览器自动帮我们校验的功能?

在form后加参数 no validate,不验证

form表单取消前端浏览器自动校验功能 
  <form action="" method="post" novalidate>

Django之form组件自动校验数据实现

常用校验参数

max_length //允许输入的最大长度
min_length //最小长度
label input的提示信息,name、password等
error_messages 自定义报错的提示信息
'max_length':"用户名最长8位",
'min_length':"用户名最短3位",
'required':"用户名不能为空"
required 设置字段是否允许为空
initial 设置默认值
widget 控制type类型及属性

使用方式

CharField用户名类型校验

from django.forms import widgets  //不导入也可以,没提示

class MyRegForm(forms.Form):
  # 用户名最少3位最多8位
  username = forms.CharField(max_length=8,min_length=3,label='用户名',
                error_messages={   //报错信息的提示
                  'max_length':"用户名最长8位",
                  'min_length':"用户名最短3位",
                  'required':"用户名不能为空"
                },required=False,initial='jeff', // 为空和默认值
                widget=forms.widgets.TextInput(attrs={'class':'form-control c1 c2'}),    //设置input的type属性为text,及class属性
                )

Django之form组件自动校验数据实现

password校验

class LoginForm(forms.Form):
  ...
  pwd = forms.CharField(
    min_length=6,
    label="密码",
    widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
  )

邮箱类型校验

class MyRegForm(forms.Form):
  # email字段必须填写符合邮箱格式的数据
  email = forms.EmailField(label='邮箱',error_messages={
    'required':'邮箱必填',
    'invalid':'邮箱格式不正确'
  })

Django之form组件自动校验数据实现

手机号类型校验

正则匹配

from django.core.validators import RegexValidator
class MyRegForm(forms.Form):
  # 手机号
  phone = forms.CharField(
    validators=[
      RegexValidator(r'^[0-9]+$', '请输入数字'),  
      RegexValidator(r'^159[0-9]+$', '数字必须以159开头')
    ]
  )

Django之form组件自动校验数据实现

性别校验

gender = forms.ChoiceField(
    choices=((1, "男"), (2, "女"), (3, "保密")),
    label="性别",
    initial=3,
    widget=forms.widgets.RadioSelect()
  )

爱好单选 select校验

hobby = forms.ChoiceField(
    choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
    label="爱好",
    initial=3,
    widget=forms.widgets.Select()  # 单选
  )

Django之form组件自动校验数据实现

爱好多选select 校验1

hobby1 = forms.MultipleChoiceField(
    choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
    label="爱好",
    initial=[1, 3],
    widget=forms.widgets.SelectMultiple()
  )

Django之form组件自动校验数据实现

爱好多选chekbox校验2

hobby2 = forms.MultipleChoiceField(
    choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
    label="爱好",
    initial=[1, 3],
    widget=forms.widgets.CheckboxSelectMultiple()
  )

Django之form组件自动校验数据实现

是否记住密码校验

keep = forms.ChoiceField(
    label="是否记住密码",
    initial="checked",
    widget=forms.widgets.CheckboxInput()
  )

Django之form组件自动校验数据实现

七、钩子函数

# 如果你想同时操作多个字段的数据你就用全局钩子
# 如果你想操作单个字段的数据 你就用局部钩子
钩子勾回来处理完之后,还要还回去的

局部钩子

校验用户名中不能包含666

# 局部钩子
# 这里的self是自己类,MyRegForm
  def clean_username(self):
    username = self.cleaned_data.get('username')
    if '666' in username:
      self.add_error('username','光喊666是不行的')
    return username

全局钩子

两次密码验证

class MyRegForm(forms.Form):
  # 密码
  password = forms.CharField(max_length=8,min_length=3,label='密码',
                widget=forms.widgets.PasswordInput(attrs={'class':'form-control'})
               )
  # 密码验证
  re_password = forms.CharField(max_length=8,min_length=3,label='确认密码',
                widget=forms.widgets.PasswordInput(attrs={'class':'form-control'})
                 )

  def clean(self):
    # 这里的self是自己类,MyRegForm
    # 校验密码和确认密码是否一致
    password = self.cleaned_data.get('password')
    re_password = self.cleaned_data.get('confirm_password')
    if not password == re_password:
      # 展示提示信息
      self.add_error('re_password','两次密码不一致')
      return self.cleaned_data

Django之form组件自动校验数据实现

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python Django使用forms来实现评论功能
Aug 17 Python
Python中跳台阶、变态跳台阶与矩形覆盖问题的解决方法
May 19 Python
python 集合 并集、交集 Series list set 转换的实例
May 29 Python
python使用matplotlib绘制热图
Nov 07 Python
详解Numpy中的数组拼接、合并操作(concatenate, append, stack, hstack, vstack, r_, c_等)
May 27 Python
python写程序统计词频的方法
Jul 29 Python
Pycharm+django2.2+python3.6+MySQL实现简单的考试报名系统
Sep 05 Python
python实现简单银行管理系统
Oct 25 Python
python实现单目标、多目标、多尺度、自定义特征的KCF跟踪算法(实例代码)
Jan 08 Python
pytorch的梯度计算以及backward方法详解
Jan 10 Python
Python实现aes加密解密多种方法解析
May 15 Python
简单了解python filter、map、reduce的区别
Jan 14 #Python
Python vtk读取并显示dicom文件示例
Jan 13 #Python
Python解析多帧dicom数据详解
Jan 13 #Python
python 将dicom图片转换成jpg图片的实例
Jan 13 #Python
基于Python和PyYAML读取yaml配置文件数据
Jan 13 #Python
Python 实现判断图片格式并转换,将转换的图像存到生成的文件夹中
Jan 13 #Python
利用python实现.dcm格式图像转为.jpg格式
Jan 13 #Python
You might like
为php4加入动态flash文件的生成的支持
2006/10/09 PHP
php文档更新介绍
2011/07/22 PHP
基于php无限分类的深入理解
2013/06/02 PHP
php通过隐藏表单控件获取到前两个页面的url
2014/09/09 PHP
php中JSON的使用方法
2015/04/30 PHP
详解Window7 下开发php扩展
2015/12/31 PHP
无语,javascript居然支持中文(unicode)编程!
2007/04/12 Javascript
关于__defineGetter__ 和__defineSetter__的说明
2007/05/12 Javascript
Jquery实现点击切换图片并隐藏显示内容(2种方法实现)
2013/04/11 Javascript
jQuery如何获取同一个类标签的所有值(默认无法获取)
2014/09/25 Javascript
为什么Node.js会这么火呢?Node.js流行的原因
2014/12/01 Javascript
javascript实现瀑布流自适应遇到的问题及解决方案
2015/01/28 Javascript
JavaScript function函数种类详解
2016/02/22 Javascript
jquery对dom节点的操作【推荐】
2016/04/15 Javascript
最佳的JavaScript错误处理实践
2016/07/16 Javascript
js中遍历Map对象的方法
2016/07/27 Javascript
Angular实现下载安装包的功能代码分享
2017/09/05 Javascript
js实现以最简单的方式将数组元素添加到对象中的方法
2017/12/20 Javascript
web前端vue之vuex单独一文件使用方式实例详解
2018/01/11 Javascript
AngularJS实现的鼠标拖动画矩形框示例【可兼容IE8】
2019/05/17 Javascript
Vue如何基于es6导入外部js文件
2020/05/15 Javascript
Vue 实现一个简单的鼠标拖拽滚动效果插件
2020/12/10 Vue.js
[01:34]完美“圣”典宣传片震撼发布,12.17与你不见不散
2016/12/16 DOTA
Python3.0与2.X版本的区别实例分析
2014/08/25 Python
Python编程修改MP3文件名称的方法
2017/04/19 Python
python递归函数绘制分形树的方法
2018/06/22 Python
Flask web开发处理POST请求实现(登录案例)
2018/07/26 Python
处理Selenium3+python3定位鼠标悬停才显示的元素
2019/07/31 Python
python打印直角三角形与等腰三角形实例代码
2019/10/20 Python
办理居住证介绍信
2014/01/15 职场文书
幼儿园数学教学反思
2014/02/02 职场文书
2014年教务工作总结
2014/12/03 职场文书
2015年管理人员工作总结
2015/05/13 职场文书
电影开国大典观后感
2015/06/04 职场文书
纪律委员竞选稿
2015/11/19 职场文书
python批量创建变量并赋值操作
2021/06/03 Python