• form组件


    form组件

    这里抛出一个问题

    校验:

    1.注册功能
    用户输入的用户名中 不能包含‘xxx’
    如果包含了 就提示用户 输入的内容不符合社会主义核心价值观
    用户输入的密码 不能小于三位
    如果密码少于三位 提示用户 密码太短了
    校验数据通常是前后端都有校验
    但是前端校验可有可无 哪怕再牛逼
    后端也必须要有校验 反正一句话 前端可有不校验 后端必须校验!!

    (深深的体现了开发鄙视链)

    这个时候用form组件就可以自动帮我们完成三个功能:

    1.搭建前端页面(渲染页面)
    2.获取前端用户提交的数据校验(校验数据)
    3.对数据的校验的结果 展示到前端页面给用户查看 (展示错误信息)

    我们首先需要自己写一个继承了Form的类。

    from django import forms
    class MyRegForm(forms.Form):
       username = forms.CharField(min_length=3,max_length=8)
       password = forms.CharField(min_length=3,max_length=8)
       email = forms.EmailField()
    

    如何校验数据?

    from app01 import views
                # 1.给自定义的类传一个字典
                obj = views.MyRegForm({'username':'jason','password':'12','email':'123'})
                # 2.判断数据是否全部合法
                obj.is_valid()  # 只有数据全部符合要求才会是True
                Out[4]: False
                # 3.查看符合校验规则的数据
                obj.cleaned_data
                Out[5]: {'username': 'jason'}
                # 4.查看不符合条件的数据以及不符合的原因是什么
                obj.errors
                Out[6]: 
                {
                    'password': ['Ensure this value has at least 3 characters (it has 2).'],
                    'email': ['Enter a valid email address.']
                 }
                
                # 5.校验数据的时候 默认情况下类里面所有的字段都必须传值
                obj = views.MyRegForm({'username':'jason','password':'123'})
                obj.is_valid()
                Out[12]: False
                obj.errors
                Out[13]: {'email': ['This field is required.']}
                # 6.默认情况下可以多传 但是绝对不能少传
                obj = views.MyRegForm({'username':'jason','password':'1233','email':'123@qq.com','xxx':'ooo'})
                obj.is_valid()
                Out[15]: True
    

    这里要介绍一下在pycharm里的一个功能,下面的Python Console,他会自动帮我们搭配好django环境,在这里对我们的输入返回结果,上面代码中的 Out就是返回结果。

    上述代码中,我们给自己写的form类里面传了一个字典,能看到的是只有 username 是符合要求的,其中各种 form 自带的方法都已经做出了解释,就不一一赘述了。

    如何渲染页面

    既然我们已经获得了结果,那么要怎么样才能在前端页面上展示出来呢?

    首先要注意一点 :forms组件只会帮你渲染获取用户输入(输入,选择,下拉框...)的标签 提交按钮需要你自己手动写

    三种渲染前端页面的方式

    第一种:

    {{ form_obj.as_p }} //as_p 是会把你的结果以p标签的形式展示
    {{ form_obj.as_ul}}//as_p 是会把你的结果以ul标签的形式展示
    

    这种方式的封装程度抬高了,标签的样式以及参数不方便调整,可扩展性差,不推荐使用

    第二种:

    <p>
      {{ form_obj.username.label }}{{ form_obj.username }}
    </p>
    <p>
      {{ form_obj.password.label }}{{ form_obj.password }}
    </p>
    <p>
      {{ form_obj.email.label }}{{ form_obj.email }}
    </p>
    

    这种方式扩展性高,但是需要手写大量代码,所以也不推荐。

    第三种:(推荐)

    {% for foo in form_obj %}
    <p>{{ foo.label }}{{ foo }}</p>
    {% endfor %}
    

    代码量和扩展性都很高(推荐使用)

    展示错误信息

    首先我们要把前端对我们做的校验取消掉,也就是浏览器,他会自动帮你做校验,怎么说呢,就是,如果你设置了最长的用户名为8位,这时候你是不能输入超越8位的字符的,会直接卡在那里,所以我们要取消前端帮我们做的校验,只需要在form表单中添加一个参数novalida 就可以了。

    <form action="" method="post" novalidate>
        
    展示错误信息   用对象点errors.0
    <form action="" method="post" novalidate>
        {% for foo in form_obj %}
        <p>
            {{ foo.label }}:{{ foo }}
            <span style="color: red">{{ foo.errors.0 }}</span>
        </p>
        {% endfor %}
        <input type="submit">
    </form>
    

    解题

    这个时候把我们的代码写上去,来解上面的题:

    后端代码:

    from django import forms
    from django.forms import widgets
    class MyRegForm(forms.Form):
        username = forms.CharField(min_length=3,max_length=8,label='用户名',
                             #error_messages的作用是不符合条件的时候对应的错误信息
                                   error_messages={
                                       'min_length':'用户名最短为三位',
                                       'max_length':'用户名最短为三位',
                                       'required':'用户名不能为空',
                                   },initial='我是初始值',required=False,
                                   #widget的作用是可以给标签加上样式
                                   widget=widgets.TextInput(attrs={'class':'form-control others'})
                                   )
        password = forms.CharField(min_length=3,max_length=8,label='密码',
                                   error_messages={
                                       'min_length': '密码最短为三位',
                                       'max_length': '密码最短为三位',
                                       'required': '密码不能为空',
                                   },widget=widgets.PasswordInput())
        confirm_password = forms.CharField(min_length=3, max_length=8, label='确认密码', error_messages={
            'min_length': '确认密码最短三位',
            'max_length': '确认密码最长八位',
            'required': '确认密码不能为空'
        })
        email = forms.EmailField(label='邮箱',error_messages={
                'required':'邮箱不能为空',
                'invalid':'邮箱格式不正确'
        },required=False,widget=widgets.EmailInput(attrs={'class':'form-control'}))
    
        def clean_username(self):
            username = self.cleaned_data.get('username')
            if 'xxx' in username:
                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
    
      
    
    def formmm(request):
        form_obj = MyRegForm()
        if request.method == 'POST':
            #这个对象只能穿字典过去,而我们的request.POST正好是一个字典,所以直接传进			去就好了。
            form_obj = MyRegForm(request.POST)
            if form_obj.is_valid():
                return HttpResponse('数据没问题')
        return render(request,'formmm.html',locals())
    

    前端代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>
    </head>
    <body>
    <form action="" method="post" novalidate>
        {% for foo in form_obj %}
        <p>
            {{ foo.label }}:{{ foo }}
            <span style="color: red">{{ foo.errors.0 }}</span>
        </p>
        {% endfor %}
        <input type="submit">
    </form>
    </body>
    </html>
    

    forms组件钩子函数

    钩子函数就是 针对字段 你还可以做额外的校验。

    钩子有分成局部钩子和全局钩子

    我们之前的用户名中不能有 ‘xxx’ 就是用钩子函数实现的,把它拉过来看一下。

     # 当你需要对某一个字段数据进行额外的一些列校验 你可以考虑使用钩子函数
                # 针对单个字段的  使用局部钩子
    def clean_username(self):
        #对象里有cleaned_data这个属性,拿到了里面的username来看一下
            username = self.cleaned_data.get('username')
            if 'xxx' in username:
                #不符合的话就丢进 error 里面去
                self.add_error('username','不能')
            return username #钩子勾过来了,当然要还回去了
    
     # 针对多个字段的校验 使用全局钩子      eg:校验两次密码是否一致       
        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 #这里索性就把全部都还回去了。
    
    

    如何改变inpu框的type属性值

     如何改变input框的type属性值
            widget= widgets.TextInput()
            widget=widgets.PasswordInput()
        如何让forms组件渲染出来的input框有form-control类属性
            widget= widgets.TextInput(attrs={'class':'form-control others'})  # 如果有多个类属性 空格隔开
            widget=widgets.PasswordInput(attrs={'class':'form-control others'})
               
    

    每个字段 还支持正则校验
    from django import forms
    from django.forms import Form
    from django.core.validators import RegexValidator
    class MyForm(Form):
    user = forms.CharField(
    validators=[RegexValidator(r'[1]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
    )

    补充知识

    gender = forms.ChoiceField(
            choices=((1, "男"), (2, "女"), (3, "保密")),
            label="性别",
            initial=3,
            widget=widgets.RadioSelect()
        )
    
    
        hobby = forms.ChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
            label="爱好",
            initial=3,
            widget=widgets.Select()
        )
    
        hobby1 = forms.MultipleChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
            label="爱好",
            initial=[1, 3],
            widget=widgets.SelectMultiple()
        )
    
        keep = forms.ChoiceField(
            label="是否记住密码",
            initial="checked",
            widget=forms.widgets.CheckboxInput()
        )
    
        hobby2 = forms.MultipleChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
            label="爱好",
            initial=[1, 3],
            widget=forms.widgets.CheckboxSelectMultiple()
        )
    

    1. 0-9 ↩︎

  • 相关阅读:
    1040 Longest Symmetric String (25 分)
    1087 All Roads Lead to Rome (30 分)
    数据结构与算法(十三)——红黑树1 Craftsman
    数据结构与算法(十三)——红黑树2 Craftsman
    Java基础(十一)——反射 Craftsman
    docker 安装fastdfs
    ubuntu新建用户
    pytorch函数zero_grad(),step()作用
    ubuntu挂载新硬盘并分区
    使用pytorch求梯度
  • 原文地址:https://www.cnblogs.com/chanyuli/p/11761486.html
Copyright © 2020-2023  润新知