forms组件

1简介

# 应用场景
应用于前端向后端提交数据,后端需要对数据进行校验并向前端返回结果的情况,如注册。

# 主要功能
1.生成页面可用的HTML标签
2.对用户提交的数据进行校验
3.保留上次输入内容

# 为什么不在前端校验
前端发送的数据不安全,可以认为修改,故只在前端校验是没意义的。通常前后端同时校验,双重保险。

2基本语法

2.1forms的定义

"""form在使用前要先新建类"""

例:
from django import forms
# 自定义类,并声明数据限制
class RegForm(forms.Form):
    name = forms.CharField(max_length=8, min_length=3, required=True,  # 常规限制条件
                               label="用户名",  # 设置提示信息,默认字段名首字母大写
                               widget=forms.widgets.TextInput(attrs={"class": "form-control"}),  # 设置表单类型和样式
                               initial='懒逼',  # 初始值
                               error_messages={  # 添加报错信息
                                   "max_length": "不能超过8个字符",
                                   "min_length": "不能少于3个字符",
                                   "required": "不能为空",
                                   #'invalid':'邮箱格式错误'(邮箱格式专用)
                               }
                               )
    
    pwd = forms.CharField(min_length=3,max_length=8)
    email = forms.EmailField(label='')		# 要满足邮箱格式XXX@XX.com
    
    
# 注释:  
1.上述代码书写位置:通常是在应用文件夹下单独建立一个.py文件,写在里面
2.每一种字段都默认有label属性,是该字段的提示信息,不写默认是字段名(且首字母大写)
3.字段的匹配条件还可以写正则
4.可以通过error_message属性自定义错误提示信息 

2.2后端数据校验

"""""""""""""""""""""""""""方案1"""""""""""""""""""""""""""
1.要先从前端获得数据

2.实例化
form_obj=RegForm('username':'json','password':'123','email':'123')	 # 只校验类中定义的字段,多传直接忽略,少传默认就是校验失败

3.判断数据是否符合要求
form_obj.is_valid()   # 判断是否所有数据都符合要求,返回True/False
form_obj.cleaned_data		# 返回符合要求的数据
form_obj.errors			# 返回不符合要求的数据和不符合的原因


""""""""""""""""""""""方案2(推荐)""""""""""""""""""""""
1.实例化form对象的时候,把post提交过来的数据直接传进去
form_obj = RegForm(request.POST)

2.调用form_obj方法校验数据
form_obj.is_valid() 



#例子:
def my_form(request):
	form_obj = RegForm()	# 产生空对象,用于前端第一次渲染input标签
	if request.method == "POST":
    	form_obj = RegForm(request.POST)	# 产生新的对象替换先前的对象,使得form_obj中拥有数据,这是保证form组件能记录先前数据的关键
		if form_obj.is_valid():
			return HttpResponse('合法')
	return render(request,'my_form.html',lcals())


# 注释:
1.应用form组件时前端会自动进行校验,在form表单中加入novalidate标签关闭此功能
2.后端2次实例化的对象名要一致,不然无法保存上一次书写的数据

2.3前端渲染标签

# 标签渲染之渲染input框和提示信息,不会渲染提交按钮,按钮要手动渲染

"""方案1"""
# 自动渲染input框和提示信息,
# 代码书写少,封装程度高,扩展性差
{{ form_obj.as_p }}			# 渲染在p标签中
{{ form_obj.as_ul }}		# 渲染在ul标签中
{{ form_obj.as_table }}		# 渲染在一行


"""方案2"""
# 手动渲染input框和提示信息,
# 代码书写多,扩展性好
<p>{{ form_obj.username.label}}:{{ form_obj.username}}</p>
# form_obj.username.label 渲染提示信息
# form_obj.username  渲染input框
    
    
"""方案3(推荐)"""
# 在手动渲染的基础上加上for循环,使得无论有多少字段,都3行代码搞定
{% for form in form_obj %}
	<p>{{ form.label}}:{{ form}}</p>   # form相当于form_obj.username
{% endfor%}


2.4前端展示错误信息

"""""""""""""""""""""""""""""""""前端"""""""""""""""""""""""""""""""""
例子:
{% for form in form_obj %}
	<p>
    	{{ form.label}}:{{ form}}	 # form相当于form_obj.username
        <span style='color:red'>{{ form.errors.0 }}</span>	# form.errors就是报错信息,这是一个列表,通常我们只取其中的第一条原因用于渲染
    </p>  	 
{% endfor%}

3 forms组件钩子函数(HOOK)

"""
在特定的节点自动触发,完成响应操作。
本质是对form组件进行2次校验,当某一字段form组件校验成功时,就会走钩子函数再进行校验。
"""

分类:
1.局部钩子
	只给单一字段添加校验规则
2.全局钩子 
	给多个字段添加校验规则
    
语法:
# 钩子函数定义在form类中,作为类方法存在,但会自动调用。

# 定义局部钩子,用来校验username字段,使其不能有666
    def clean_username(self):
        value = self.cleaned_data.get("username")	# 获取当前字段值
        if "666" in value:
            self.add_error('username', '不要加666') 	# 指定报错提示信息
        return value	 # 返回钩子
   

# 定义全局的钩子,用来校验密码和确认密码字段是否相同
    def clean(self):
        password_value = self.cleaned_data.get('password')
        re_password_value = self.cleaned_data.get('re_password')
        if not password_value == re_password_value:
            self.add_error('re_password', '两次密码不一致')
        return self.cleaned_data

4字段的属性

label  			# 提示信息
error_message 	 # 自定义报错信息
initial			# 默认值
required 		# 控制字段是否必需要填写(能否为空),true/false



如何修改标签样式和属性?
# widget修改标签样式
# 括号中写attrs={}填写标签属性,以字典的形式传参,多个属性值用空格隔开

widget=forms.widgets.TextInput(attrs={'class':'form-control',})	  	# 文本框
widget=forms.widgets.PasswordInput()	# 密文输入框
widget=forms.widgets.EmailInput()



自定义正则校验规则 

validators=[
    RegexValidator(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$','错误提示信息'),
	RegexValidator(),		# 可以写多条
]

5补充其它渲染标签样式

# radio
gender = forms.ChoiceField(
        choices=((1, "男"), (2, "女"), (3, "保密")),
        label="性别",
        initial=3,
        widget=forms.widgets.RadioSelect()
    
# 单选checkbox
keep = forms.ChoiceField(
        label="是否记住密码",
        initial="checked",
        widget=forms.widgets.CheckboxInput()

# 多选checkbox
hobby = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()
    
# 单选Select
 hobby = forms.ChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=3,
        widget=forms.widgets.Select()
     
# 多选Select 
hobby = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
posted @ 2021-08-31 15:27  hai437  阅读(60)  评论(0编辑  收藏  举报