• Django框架(十五)—— forms组件、局部钩子、全局钩子


    forms组件、局部钩子、全局钩子

    一、什么是forms组件

    forms组件就是一个类,可以检测前端传来的数据,是否合法。
    例如,前端传来的邮箱数据,判断邮件格式对不对,用户名中不能以什么开头,等等

    二、forms组件的使用

    1、使用语法

    from django.shortcuts import render, HttpResponse
    from django import forms
    
    # 1.先写一个类,继承Form
    class MyForm(forms.Form):
        # 定义一个属性,可以用来校验字符串类型
        # 限制最大长度是8,最小长度是3
        name=forms.CharField(max_length=8,min_length=3)
        pwd=forms.CharField(max_length=8,min_length=3,required=True)
        # 校验是否是邮箱格式
        email=forms.EmailField()
    
        
    
    # 2.在视图函数中使用MyForm来校验数据
    # 实例化产生对象,传入要校验的数据(可以传字典字典,也可以不传)
    myform=MyForm(request.POST)
    
    # 3.校验,is_valid如果是true表示校验成功(满足myform里的条件),反之,校验失败
    if myform.is_valid():
        # myform.clean_data 表示校验通过的数据
        print(myform.cleaned_data)
        return HttpResponse('校验成功')
    else:
        print(myform.cleaned_data)
        #校验失败的信息,myform.errors  可以当成一个字典,它是所有错误信息{name:[列表,]}
        # 每个字段.errors 是一个列表,表示每个字段的错误信息
        print(myform.errors)
        return HttpResponse('校验失败')
    

    方法总结:

    • myform.clean_data 验证通过的数据
    • myform.errors 错误数据的对象
    • myform.errors.as_data 错误数据的信息

    2、组件的参数

    max_length    # 代表该字段最长为多少
    min_length    # 代表该字段最短为多少
    error_messages   # 这是设置错误信息的属性
    required   # 默认值为True,意思是你传来的字段必须有它,没有的话校验失败
    widget=widgets.TextInput()  # 你在模板渲染的时候,就会渲染成Input框,type为text
    lable   # lable='用户名'
    
    # 例子
     pwd = forms.CharField(max_length=8, min_length=3, required=True, label='密码',
                              error_messages={'max_length': '最长是8', 'min_length': '最短是3', 'required': '这个必须填'},

    3、注意点

    • MyForm实例化时,传入必须是字典,或者不传
    • errors 调用这个方法,返回值是对象,你可以通过get取值
    • 要校验的数据,字段可以多于MyForm类中的字段,但不能少,少相当于该字段没有数据

    三、渲染模板

    # form组件可以在视图函数中使用,也可以在模板中使用
    # 视图层:
    def index(request):
        myform = Myform()
        return render(request,'index.html',local())
    # 模板层
    # 1.渲染方式一:
        <form action='' method='post'>
            用户名:{{myform:name}} <br>
            <input type='submit' value = '提交'></input>
        </form>
        # 这里的{{myform:name}} 和你写input框是一样的效果,就是属性比input框多一点
    
    # 2.渲染方式二(推荐使用):
        <form action='' method='post'>
            {% for foo in myform%}
                {{ foo.lable }} : {{ foo }}  <br>
            <input type='submit' value = '提交'></input>
        </form>
        # 页面显示都是一样的,foo.lable不是用户名,是name,但是可以在创建Myform类时,在CharFiel中添加lable='用户名',这样就行了。
    
    # 3.渲染方式三:
        <form action='' method='post'>
             {{ myform.as_p }}
            <input type='submit' value = '提交'></input>
        </form>

    四、渲染错误信息

    <form action='' method='post'>
        {% for foo in myform%}
            {{ foo.lable }} : {{ foo }} <span>{{foo.errors.0}}</span><br>
        <input type='submit' value = '提交'></input>
    </form>

    五、局部钩子

    1、什么是局部钩子

    定义一个函数,名字叫:clean_字段名字,内部,取出该字段,进行校验,如果通过,将该字段返回,如果失败,抛异常(ValidationError)

    2、定义局部钩子

    # 函数名:clean_字段名字
    def clean_name(self):
        # self:当前form对象
        name = self.cleaned_data.get('name')
        if name.startswith('sb'):
            # 失败,抛异常,将异常信息以 {'name':value} 写入errors字典中
            raise ValidationError('不能以sb开头')
        # 正常,把name返回到clean_data,将name写入clean_data字典中
        return name

    注意点:

    • 校验失败,抛异常,将异常信息以 {'name':value} 写入 errors 字典中
    • 校验成功,把name返回到clean_data,写入clean_data字典中
    • 抛出异常的类型为ValidationError,from django.core.exceptions import ValidationError导入

    六、全局钩子

    1、什么是全局钩子

    在写注册用户的时候,有输入密码,确认密码,可以进行布局钩子处理,处理完毕是不是在进行判断,判断他们是否相等,相等的话,就存到数据库中,不相等就抛个异常。

    2、定义全局钩子

    # 重写clean方法
    def clean(self):
        # 程序能走到该函数,前面校验已经通过了,所以可以从cleaned_data中取出密码和确认密码        
        pwd=self.cleaned_data.get('pwd')
        re_pwd=self.cleaned_data.get('re_pwd')
        # 进行自己的校验
        if pwd==re_pwd: 
            # 通过,直接返回cleaned_data
            return self.cleaned_data
        else:
            # 失败,抛异常(ValidationError)
            raise ValidationError('两次密码不一致')
            

    全局钩子注意点:

    • 校验失败,抛异常,将异常信息以{'__all__':[value,]} 写入 errors 字典中
    • 校验成功,返回clean_data字典
    • 抛出异常的类型为ValidationError,from django.core.exceptions import ValidationError导入

    钩子错误信息渲染注意点:

    • 局部钩子抛出的异常会添加到该字段中的错误信息中,获取错误信息:

      前台:for循环生成input框,{{ foo.errors.0 }}

    • 全局钩子抛出的异常会添加到_all_中,获取错误信息:

      后台:myforms.errors.get('__all__')[0]注意先判断myforms.errors.get('__all__')是否存在
      前台:{{ myforms.errors.__all__.0 }}

    • 如果程序走到了局部钩子这一步,说明传的字典里的数据符合要求,此时就可以从clean_data中取数据,因为此时clean_data中的数据全符合要求,而且clean_data是一个字典

    • 局部钩子,全局钩子所抛出异常的类型为ValidationError,以下导入

    from django.core.exceptions import ValidationError

    七、完整的forms组件校验

    1、视图层

    from django.shortcuts import render, HttpResponse, redirect
    
    # forms组件数据校验的功能
    # 第一步:先要继承Form
    from django import forms
    from django.forms import widgets
    from django.core.exceptions import ValidationError
    
    
    # 写一个类
    class MyForm(forms.Form):
        # 定义一个属性,可以用来校验字符串类型
        # 限制最大长度是8,最小长度是3
        name = forms.CharField(max_length=8, min_length=3, label='用户名'
                               error_messages={'max_length': '最长是8', 'min_length': '最短是3', 'required': '这个必须填'},
                               widget=widgets.TextInput(attrs={'class': 'form-control'}))
        
        pwd = forms.CharField(max_length=8, min_length=3, required=True, label='密码',
                              error_messages={'max_length': '最长是8', 'min_length': '最短是3', 'required': '这个必须填'},
                              widget=widgets.PasswordInput())
        
        re_pwd = forms.CharField(max_length=8, min_length=3, required=True, label='确认密码',
                                 error_messages={'max_length': '最长是8', 'min_length': '最短是3', 'required': '这个必须填'},
                                 widget=widgets.PasswordInput())
        # 校验是否是邮箱格式
        email = forms.EmailField(label='邮箱', error_messages={'required': '这个必须填', 'invalid': '不符合邮箱格式'})
    
        # aa = forms.CharField(label='选择', error_messages={'required': '这个必须填', 'invalid': '不符合邮箱格式'},widget=widgets.CheckboxInput())
        def clean_name(self):
            # self:当前form对象
            name = self.cleaned_data.get('name')
            if name.startswith('sb'):
                # 失败,抛异常
                raise ValidationError('不能以傻逼开头')
            # 正常,把name返回
            return name
    
        def clean(self):
            pwd = self.cleaned_data.get('pwd')
            re_pwd = self.cleaned_data.get('re_pwd')
            if pwd == re_pwd:
                return self.cleaned_data
            else:
                raise ValidationError('两次密码不一致')
    
    
    def index_form(request):
        # 生成对象时(实例化),需要传入要校验的数据(字典)
        if request.method == 'GET':
            myform = MyForm()
            return render(request,'indxe2.html',locals())
        elif request.method == 'POST':
            myform = MyForm(request.POST)
            if myform.is_valid():
                # print(myform.cleaned_data)   # 验证通过的数据
                # models.User.objects.create(name='lqz',pwd='123',re_pwd='123)
                myform.cleaned_data.pop('re_pwd')
                models.User.objects.create(**myform.cleaned_data)
                return redirect('http://www.baidu.com')
            else:
                all_error = myform.errors.get('__all__')
                if all_error:
                    all_error = all_error[0]
                 # print(myform.errors.as_data)
    
        return render(request, 'indxe3.html', locals())
    

    2、模板层

    <form action="" method="post" novalidate>
        {% for foo in myform %}
            <p>{{ foo.label }}:{{ foo }} <span>{{ foo.errors.0 }}</span></p>
        {% endfor %}
    
        <input type="submit" value="提交"><span>{{ all_error }}</span>
    </form>

    注意点:

    • 局部钩子的错误信息:

      前台:for循环生成input框,{{ foo.errors.0 }}

    • 全局钩子的错误信息:

      后台:myforms.errors.get('__all__')[0]注意先判断myforms.errors.get('__all__')是否存在
      前台:{{ myforms.errors.__all__.0 }}

    • 校验全部通过,创建数据时,从clean_data中获取数据,但是必须要将其中多于的数据pop掉,如clean_data.pop('r_pwd')

    博客内容仅供参考,部分参考他人优秀博文,仅供学习使用
  • 相关阅读:
    Expression 学习 [1]
    代码格式化工具 CodeMaid
    深度复制
    Linq to entity 笔记
    Linq To SQL Update Delete
    sphinx 安装 笔记
    过滤HTML 脚本 样式 避免样式冲突
    TFS 文件显示 未下载 却无法下载到本地 文件路径版定问题解决
    生成实体文件 需要用到的SQL 语句
    应用程序 数据缓存
  • 原文地址:https://www.cnblogs.com/zhuzhiwei-2019/p/10779168.html
Copyright © 2020-2023  润新知