form组件

form组件前戏

"""
练习
页面上获取用户输入的用户名和密码
然后判断用户名和密码是否符合一些条件 如果不符合则返回相应的提示信息
"""

# 后端代码
def home(request):
   dict_data = {'username': '', 'password': ''}
   # 先定义一个字典,当get请求时,值为空,不会在html页面显示,而为POST请求时会对字典进行赋值,进行if判断,这样我们就能在html界面显示提示信息
   if request.method == "POST":
       username = request.POST.get('username')
       passwd = request.POST.get('password')
       if username == 'jason': # 数据校验
           dict_data['username'] = '内容不合法' # 提示信息
       if len(passwd) < 3:
           dict_data['password'] = '密码不能少于3位数'
   return render(request, 'home.html',locals())

# 前端简易代码

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
   <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<form action="" method="post">
   <p>用户名
       <input type="text" name="username">
       <span style="color: red">{{ dict_data.username }}</span>
       # span标签为行内标签,用来接收后端传过来的值
   </p>
   <p>密码
       <input type="text" name="password">
       <span style="color: red">{{ dict_data.password }}</span>
   </p>
   <input type="submit" value="提交">
</form>

</body>
</html>


自定义数据校验功能 主要步骤
1.搭建前端页面 标签渲染
2.校验数据是否合法   数据校验
3.返回相应的提示信息  提示信息
# 上述的三个步骤form组件都可以自动实现

form组件基本定义

# 与模型层类的定义相似
先导模块
from django import forms
class MyForm(forms.Form):
   # username字段最短三位最长八位
   username = forms.CharField(min_length=3, max_length=8)
   # password字段最短三位最长八位
   password = forms.CharField(min_length=3, max_length=8)
   # email字段必须符合邮箱格式
   email = forms.EmailField()

form组件数据校验功能

功能测试

class User(forms.Form):
   username = forms.CharField(min_length=3,max_length=8)
   password = forms.CharField(min_length=3,max_length=8)
   email = forms.EmailField()

# 1.传入待校验的数据
from app01 import views
obj = views.MyForm({'username':'jason',
                   'password':'123',
                   'email':'123@qq.com'
                  })
# 2.判断所有的数据是否合规
obj.is_valid()  # 结果是布尔值(只有所有的数据都合规才返回True)
# 3.如何查看符合条件校验的数据
obj.cleaned_data  # 字典(所有通过校验的数据)
# 4.如何查看不符合条件检验的数据和错误的原因
obj.errors
"""
1.在传递数据的时候 如果多传了额外字段 没有关系   form不校验
2.form组件内部定义的字段数据 默认都是必填的
可以通过修改参数required=False来控制是否必填
"""

form组件渲染标签

def my_form(request):
   # 1.直接生成一个不传参数的form对象
   obj = MyForm()
   return render(request,'my_form.html',locals())
"""
自动渲染的标签文本名称默认采用字段名首字母大写的形式
可以通过label参数自定义名称
form只渲染获取用户数据的标签 不渲染提交按钮 需要我们自己编写
"""

# 渲染标签的方式1
{{ obj.as_p }}  # 封装程度太高 扩展不易 通常用于本地测试
  {{ obj.as_ul }}
  {{ obj.as_table }}
   
   可以在后端字段上添加label参数label='用户名'
   
# 渲染标签的方式2
   <label for="{{ obj.username.id_for_label }}">{{ obj.username.label }}</label>
  {{ obj.username }}  # 扩展性高 但是书写麻烦
   
   <p>{{ obj.username.label }}:{{ obj.username }}</p>
   <p>{{ obj.password.label }}:{{ obj.password }}</p>
    有多少个字段,就需要写多少行,比较麻烦
   
# 渲染标签的方式3
{% for foo in obj %}
       <p>
           <label for="{{ foo.id_for_label }}">{{ foo.label }}</label>
          {{ foo }}  # 融合了方式1和方式2的优势(推荐使用)
       </p>
  {% endfor %}

form组件提示信息(渲染错误信息)

# 渲染错误信息

'浏览器会自动帮我们校验数据,但是前端的校验弱不禁风(用户可以修改),所以我们要取消前端的校验,采取后端校验的方式'

# 如何取消前端自动校验
<form ... novalidate></form>

# 前端提前配置好
{{ foo.errors.0 }}

# 后端自定义提示信息
error_messages={
       'min_length': '用户名最少3位',
       'max_length': '用户名最大8位',
       'required': '用户名不能为空',
       'invalid':'邮箱格式不正确'
  }
   
   
# 信息校验错误信息提示

from django import forms
class User(forms.Form):
   username = forms.CharField(min_length=3,max_length=8,label='用户名', # label是自定义字段名称
                              error_messages={'min_length':'用户名至少要3个字符',
                                              'max_length':'最多只能8个字符',
                                              'required':'用户名不能为空'
                                              }   # error_messages参数是自定义错误提示信息
                              )
   password = forms.CharField(min_length=3,max_length=8,label='密码',
                              error_messages={'min_length':'密码至少要3个字符',
                                              'max_length':'最多只能8个字符',
                                              'required':'密码不能为空'
                                              }
                              )
   email = forms.EmailField(label='邮箱',error_messages={'required':'邮箱不能为空',
                            'invalid':'邮箱格式不正确'}
                            )


def form_data(request):
   form_obj = User() # 生成一个空对象
   if request.method == "POST":
       form_obj = User(request.POST) # 获取浏览器post请求数据(request.POST是一个字典格式)
       if form_obj.is_valid(): # 判断浏览器输入的数据是否符合规范
           return HttpResponse('ok')
   return render(request,'form_data.html',locals())

当浏览器请求方式为get时,会生成一个空对象,直接返回'form_data.html'页面,这时前端span标签没有内容,所以不会有显示,而当为post请求时,会将前端提交的数据给到form_obj对象
# 必备条件:get请求和post请求返回给html页面的对象变量名必须一致(即form_obj对象)
# form组件当你输入的数据不合法时,会自动帮你保存当前界面,方便修改,比较人性化

# 前端代码
<form action=""method="post" novalidate> # novalidate取消浏览器自动校验
{% for foo in form_obj %}
   <p>
   <label for="{{ foo.id_for_lable }}">{{ foo.label }}</label>:
  {{ foo }}
   <span style="color: red">{{ foo.errors.0 }}</span> # 获取错误信息
   </p>
  {% endfor %}
   <button>提交</button>

</form>

数据校验进阶之正则校验

# 正则校验(相当于form表单的第二层校验)
from django.core.validators import RegexValidator
class MyForm(Form):
   user = fields.CharField(
       validators=[
           RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
  )
   

数据校验进阶之钩子函数

钩子函数(hook)在特定的节点自动触发完成响应操作(相当于form表单的第三层校验)
能够让我们自定义校验规则

# 钩子函数(基本校验规则完毕之后 产生了cleaned_data数据后才会执行钩子函数)
# 局部钩子(单个字段校验):校验用户名是否已存在
def clean_username(self):
   # 获取用户名数据
   username = self.cleaned_data.get('username')
   # 校验用户名是否已存在
   if username == 'jason':
       # 添加用户名提示信息
       self.add_error('username', '用户名已存在')
       return username

# 全局钩子(多个字段校验):校验密码与确认密码是否一致
def clean(self):
   # 获取密码
   password = self.cleaned_data.get('password')
   # 获取确认密码
   confirm_password = self.cleaned_data.get('confirm_password')
   # 比对密码是否一致
   if not password == confirm_password:
      # 添加提示信息
      self.add_error('confirm_password', '两次密码不一致')
      return self.cleaned_data

 

form组件补充

# 参数部分
label 字段名称
   required 是否必填
   initial 默认值
   error_messages  自定义错误信息
   
   1、字段没有样式
   2、针对不同input无法修改类型
   '''
  text
  password
  file
  radio
  checkbox
  date
  email
  '''
   可以使用widget方法
   widget=forms.widgets.PasswordInput(attrs={'class':'form_control'})  # 可以以字典格式添加多个样式,用空格隔开即可
  既可以修改input框的type类型
       还可以操作标签的属性

form组件源码探索

"""阅读源码是提升编程思维的最佳方式!!!"""
# 突破口在
obj.is_valid()

 

posted @ 2021-12-07 19:38  一叶松  阅读(53)  评论(0编辑  收藏  举报