zoukankan      html  css  js  c++  java
  • 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 ↩︎

  • 相关阅读:
    949. Largest Time for Given Digits
    450. Delete Node in a BST
    983. Minimum Cost For Tickets
    16. 3Sum Closest java solutions
    73. Set Matrix Zeroes java solutions
    347. Top K Frequent Elements java solutions
    215. Kth Largest Element in an Array java solutions
    75. Sort Colors java solutions
    38. Count and Say java solutions
    371. Sum of Two Integers java solutions
  • 原文地址:https://www.cnblogs.com/chanyuli/p/11761486.html
Copyright © 2011-2022 走看看