• Django之forms组件


    forms组件

    例如我们写一个注册功能,要求是:

    ​ 用户输入的用户名中 不能包含666
    ​ 如果包含了 就提示用户 输入的内容不符合社会主义核心价值观
    ​ 用户输入的密码 不能小于三位
    ​ 如果密码少于三位 提示用户 密码太短了

    这就需要搭建前端页面,对前端用户提交的数据进行校验,将错误信息展示到前端页面给用户看

    要注意的是:校验数据通常是前后端都有校验
    但是前端校验可有可无 哪怕再牛逼
    后端也必须要有校验 反正一句话 前端可有不校验 后端必须校验!!!

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

    forms组件能够自动帮你完成三件事:

    1. 渲染页面
    2. 校验数据
    3. 展示信息

    forms组件基本用法

    1、首先要先写一个类

    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()
    

    2、如何校验数据

    在pycharm下面的Python Console窗口中进行校验测试,会自动搭建测试环境

    测试代码:

    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.']}  # 没有给表中的email字段传值,就无法通过校验
        
    # 6.默认情况下可以多传 但是绝对不能少传
    obj = views.MyRegForm({'username':'jason','password':'1233','email':'123@qq.com','xxx':'ooo'})
    obj.is_valid()
    Out[15]: True
    

    渲染页面

    注意事项:

    ​ 1.forms组件在帮你渲染页面的时候 只会渲染获取用户输入(输入,选择,下拉框...)的标签 提交按钮需要你手动添加
    ​ 2.input框的label注释 不指定的情况下 默认用的类中字段的首字母大写

    三种渲染前端页面的方式

    后端

    from django import forms
    
    class MyRegForm(forms.Form):
    	username = forms.CharField(min_length=3,max_length=8,label='用户名')
    	password = forms.CharField(min_length=3,max_length=8,label='密码')
    	email = forms.EmailField(label='邮箱')
        
    def formmm(request):
        # 1.生成一个空的对象
        form_obj = MyRegForm()
        if request.method == 'POST':
            # 2.获取用户提交的数据
            # print(request.POST)  # request.POST  其实也可以看成是一个字典
            # 3.借助于form组件帮助我们校验
            form_obj = MyRegForm(request.POST)  # 由于request.POST其实就是一个大字典 所以直接当做参数传入即可  # 注意:这个form_obj对象名必须跟上面的form_obj对象名一致
            # 4.判断用户输入的数据是否符合校验规则
            if form_obj.is_valid():
                return HttpResponse('你上传的数据没有问题')
        return render(request,'formmm.html',locals())
    

    第一种渲染页面的方式(封装程度太高,标签样式及参数不方便调整,可扩展性差,一般只用于本地测试 不推荐使用)

    <p>
    {{ form_obj.as_p }}  
    {{ form_obj.as_ul }}
    {{ form_obj.as_table }}    
    </p>
    
    

    第二种渲染页面的方式:扩展性较高,但不足之处在于需要手写的代码量比较多(不推荐使用)

    <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>
    			
    

    第三种渲染前端页面的方式:代码量比较少,可扩展性都很高(推荐使用)

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

    想要input框前的名字是中文,在后端的字段中直接加参数label='用户名'

    eg :

    # views.py
    from django import forms
    class MyRegForm(forms.Form):
    	username = forms.CharField(min_length=3,max_length=8,label='用户名')
    	password = forms.CharField(min_length=3,max_length=8,label='密码')
    	email = forms.EmailField(label='邮箱')
    

    如何展示错误信息

    取消前端校验功能

    校验数据的时候可以前后端都校验 做一个双重的校验,但是前端的校验可有可无,而后端的校验则必须要有,因为前端的校验可以通过爬虫直接避开。
    前端取消浏览器校验功能:form标签添加novalidate属性即可:<form action="" method='post' novalidate></form>

    展示错误信息

    展示错误信息:用后端传过来的对象.errors.0

    form action="" method="post" novalidate>
        {% for foo in form_obj %}
        <p>
            {{ foo.label }}:{{ foo }}   <!--渲染前端页面-->
            <span style="color: red">{{ foo.errors.0 }}</span>   <!--展示错误信息显示在input框的后面-->
        </p>
        {% endfor %}
        <input type="submit">
    </form>
    

    上述的方法展示出来的错误信息时英文,那怎么把它变成中文显示呢,来看以下代码:

    from django import forms
    
    class MyRegForm(forms.Form):
    	username = forms.CharField(min_length=3,max_length=8,label='用户名',
                                  # 指定error_messages参数来把错误信息用中文展示出来
    							error_messages={    
    								'min_length':'用户名最短三位',  
    								'max_length':'用户名最长八位',
    								'required':'用户名不能为空'
    							},initial='我是初始值'  # 这个参数是给input框设置初始值
    							)
    
    	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)   # 把required参数指定为False,表示这个字段的参数可以不传,如果传了的话也依然还是会校验的。
    

    forms组件钩子函数

    当你需要对某一个字段数据进行额外的一系列校验,可以考虑使用钩子函数

    钩子函数是forms组件暴露给用户,可以自定义的校验规则

    必须通过字段本身之前的校验规则,才会进行钩子函数的校验。

    用法:在自定义的form类中书写方法即可

    局部钩子

    针对单个字段的,使用局部钩子

    # 局部钩子(针对某一个字段做额外的校验)   校验用户名中不能包含666 一旦包含 提示
    def clean_username(self):
    	username = self.cleaned_data.get('username')
    	if '666' in username:
    		# 给username字段下面提示错误信息
    		self.add_error('username','光喊666是不行的 你得自己上')
    	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
    			
    

    forms组件其他字段及操作方式

    required 是否必填
    label 注释信息
    error_messages 报错信息
    initial 默认初始值
    widget 控制标签属性和样式

    如何改变input框的type属性值

    需要给字段指定widget参数来控制标签属性

    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'})

    eg:

    from django import forms
    from django.forms import widgets  # 当你forms点不出来的时候 你可以手动导入一下
    
    class MyRegForm(forms.Form):
        username = forms.CharField(min_length=3,max_length=8,label='用户名',
                                   error_messages={
                                       'min_length':'用户名最短三位',
                                       'max_length':'用户名最长八位',
                                       'required':'用户名不能为空'
                                   },initial='我是初始值',required=False,
                                   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())
    	email = forms.EmailField(label='邮箱',error_messages={
                'required':'邮箱不能为空',
                'invalid':'邮箱格式不正确'
        		},required=False,widget=widgets.EmailInput(attrs={'class':'form-control'}))
    

    其他字段了解知识点(知道有这些对象 需要用到的时候 能够知道去哪找)

    # 单选的radio框
    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()
    )
    
    # 多选的select框
    hobby1 = forms.MultipleChoiceField(
    	choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
    	label="爱好",
    	initial=[1, 3],
    	widget=forms.widgets.SelectMultiple()
    )
    
    # 单选的checkbox框
    keep = forms.ChoiceField(
    	label="是否记住密码",
    	initial="checked",
    	widget=forms.widgets.CheckboxInput()
    )
    
    # 多选的checkbox框
    hobby2 = forms.MultipleChoiceField(
    	choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
    	label="爱好",
    	initial=[1, 3],
    	widget=forms.widgets.CheckboxSelectMultiple()
    )
    

    每个字段,还支持正则校验

    需要导入RegexValidator模块

    eg:

    from django import forms
    from django.forms import Form
    from django.core.validators import RegexValidator
             
    class MyForm(Form):
    	phone = forms.CharField(label='手机号',
    		validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
             )
    
  • 相关阅读:
    【整理】PHP获取客户端真实IP地址详解
    配置百度编辑器变成纯代码编辑器
    Notepad++安装SVN插件
    【CodeBase】【转】php随机生成汉字
    【CodeBase】PHP打印所有用户自定义常量
    php5.3新垃圾回收机制详解
    php脚本cli 模式运行
    php 内存分配新
    php-fpm epoll封装
    火焰图定位dbproxy问题
  • 原文地址:https://www.cnblogs.com/zhuangyl23/p/11761129.html
Copyright © 2020-2023  润新知