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编程中的包结构
Oct 25 Python
关于反爬虫的一些简单总结
Dec 13 Python
python并发2之使用asyncio处理并发
Dec 21 Python
python3+PyQt5+Qt Designer实现堆叠窗口部件
Apr 20 Python
Python实现的求解最大公约数算法示例
May 03 Python
Python运维自动化之nginx配置文件对比操作示例
Aug 29 Python
python全栈要学什么 python全栈学习路线
Jun 28 Python
python 字符串常用函数详解
Sep 11 Python
读取nii或nii.gz文件中的信息即输出图像操作
Jul 01 Python
Python 爬虫性能相关总结
Aug 03 Python
浅谈Python数学建模之数据导入
Jun 23 Python
python单向链表实例详解
May 25 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
深入解析PHP中的(伪)多线程与多进程
2013/07/01 PHP
分享ThinkPHP3.2中关联查询解决思路
2015/09/20 PHP
Yii2数据库操作常用方法小结
2017/05/04 PHP
Flash+XML滚动新闻代码 无图片 附源码下载
2007/11/22 Javascript
EXT中xtype的含义分析
2010/01/07 Javascript
Three.js源码阅读笔记(物体是如何组织的)
2012/12/27 Javascript
多个表单中如何获得这个文件上传的网址实现js代码
2013/03/25 Javascript
JavaScript中setUTCMilliseconds()方法的使用详解
2015/06/12 Javascript
javascript实现给定半径求出圆的面积
2015/06/26 Javascript
JavaScript 继承详解(五)
2016/10/11 Javascript
jQuery居中元素scrollleft计算方法示例
2017/01/16 Javascript
微信小程序 ecshop地址三级联动实现实例代码
2017/02/28 Javascript
老生常谈js中0到底是 true 还是 false
2017/03/08 Javascript
AngularJS实现进度条功能示例
2017/07/05 Javascript
React中使用collections时key的重要性详解
2017/08/07 Javascript
vue2.0移除或更改的一些东西(移除index key)
2017/08/28 Javascript
微信小程序中post方法与get方法的封装
2017/09/26 Javascript
在iFrame子页面里实现模态框的方法
2018/08/17 Javascript
配置eslint规范项目代码风格
2019/03/11 Javascript
原生js无缝轮播插件使用详解
2020/03/09 Javascript
vue实现瀑布流组件滑动加载更多
2020/03/10 Javascript
html+vue.js 实现漂亮分页功能可兼容IE
2020/11/07 Javascript
python和bash统计CPU利用率的方法
2015/07/10 Python
python中range()与xrange()用法分析
2016/09/21 Python
Python爬虫包BeautifulSoup异常处理(二)
2018/06/17 Python
Python实现截取PDF文件中的几页代码实例
2019/03/11 Python
Python中dict和set的用法讲解
2019/03/28 Python
Python高级特性——详解多维数组切片(Slice)
2019/11/26 Python
PyTorch中反卷积的用法详解
2019/12/30 Python
python用tkinter实现一个简易能进行随机点名的界面
2020/09/27 Python
Pandora西班牙官方商店:PandoraShop.es
2020/10/05 全球购物
公司市场部岗位职责
2013/12/02 职场文书
先进德育工作者事迹材料
2014/01/24 职场文书
用人单位终止解除劳动合同证明书
2014/10/06 职场文书
乡镇党的群众路线教育实践活动制度建设计划
2014/11/03 职场文书
实验室安全管理制度
2015/08/05 职场文书