FORMS组件

前奏

当我们在一个网页注册信息的时候,会有一些提示信息,这些提示信息是如何展示在页面的呢?

小例子

前端
<form action="" method="post">
    <p>username: <input type="text"></p>
    <span style="color: red">{{ back_msg.username }}</span>
    <p>password: <input type="password"></p>
        <span style="color: red">{{ back_msg.password }}</span>
    <input type="submit" value="确定">
</form>

后端
def reg(request):
    back_msg = {'username':'','password':""}
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')

        if '啊啊' in username:
            back_msg['username'] = '不符合条件'
        if len(password)<3:
            back_msg['password'] = '密码太短了'

    return render(request,'reg.html',locals())


有人会问数据的校验为什么不在前端取完成呢,前端的校验数据可有可无,如果你在前端校验,人家可以直接修改,绕过前端抽后端提交数据,所以必须在后端完成数据的校验

基本使用

from django import forms

class RegForm(form.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 forms

reg_form = forms.RegForm({'username':'zc','password':'....','email':'123'})

reg_form.is_valid()  # 判断是否合法
False

reg_form.cleaned_data # 查看所有通过校验的数据
{'username':'zc','password':'....'}

reg_form.errors #  查看所有不符合校验规则以及原因
{
  'email': ['Enter a valid email address.']
}

但是校验数据类中出现的字段,你多传了不会有影响,直接忽略,但是你少,你在校验数据的时候就会是False

渲染标签

forms组件会帮你渲染用户输入的标签,不能帮你渲染提交按钮

第一步:

def reg(request): 
    reg_form = forms.RegForm() # 先产生一个空对象
    return render(request,'reg.html',locals())

第二步

{# 第一种渲染方式 #}
{{ reg_form.as_p }}
{{ reg_form.as_ul }}
{{ reg_form.as_table }}

{# 第二种方式 #}
{{ reg_form.username.label }}:{{ reg_form.username }}
{{ reg_form.password.label }}:{{ reg_form.password }}
{{ reg_form.email.label }}:{{ reg_form.email }}

{# 第三种 #}
{% for foo in reg_form %}
    {{ foo.label }}:{{ foo }}
{% endfor %}

第一种封装性太高,不利于扩展,第二种代码量太多,我们可以使用第三种,扩展性也高

展示校验的提示信息

如果不想让前端帮你做校验信息,<form action="" method="post" novalidate>加上这个

<form action="" method="post" novalidate>
{% for foo in reg_form %}
    {{ foo.label }}:{{ foo }}
    <span style="color: red">{{ foo.errors.0 }}</span>

{% endfor %}
    <input type="submit">

后端:

def reg(request):
    reg_form = forms.RegForm() # 1. 先产生一个空对象
    if request.method == 'POST':
         # 获取用户数据并且校验
        """
        1.数据获取繁琐
        2.校验数据需要构造成字典的格式传入才行
        ps:但是request.POST可以看成就是一个字典
        """
        reg_form = forms.RegForm(request.POST)# 3.校验数据
        if reg_form.is_valid():# 4. 判断是否合法,合法执行下面的,操作数据存储数据
            return HttpResponse('OK') 
     # 直接将该空对象传递给html页面  
    return render(request,'reg.html',locals())


get请求和post传给html页面对象变量名必须一样,forms组件当你的数据不合法的情况下 会保存你上次的数据 让你基于之前的结果进行修改,更加的人性化,但是你前面必须加上一个空对象,校验数据的变量名和产生空对象的变量名一致

针对错误的提示信息我们还可以自己定制


class RegForm(forms.Form):
    username = forms.CharField(min_length=4,max_length=32,label='账号',
                               error_messages=
                                    {'min_length': '最小4位',
                                    'max_length': '最大32位',
                                     'required':'账号不能为空'})
    
    password = forms.CharField(min_length=6,max_length=12,label='密码', 												error_messages=
                                    {'min_length': '最小6位',
                                    'max_length': '最大12位',
                                     'required':'面膜不能为空'})
    
    email = forms.EmailField(label='邮箱',error_messages={'invalid': '邮箱格式不正确',
                                                        'required': '邮箱不能为空'})

HOOK

局部钩子: 当你需要给单个字段增加校验规则的时候可以使用

  def clean_username(self):
        # 获取用户名
        username = self.cleaned_data.get('username')
        if '666' in username:
            # 提示前端展示错误信息
            self.add_error('username','老铁666,不刷礼物吗')
        # 将钩子函数勾出来的数据再放回去
        return self.username

全局钩子:当你需要给多个字段增加校验规则的时候可以使用

如:校验密码和确认密码是否一样

def clean(self):
        password = self.cleaned_data.get('password')
        confirm_password = self.cleaned_data.get('confirm_password')
        if not confirm_password == password:
            self.add_error('confirm_password','两次密码不一致')
        # 将钩子函数钩出来数据再放回去
        return self.cleaned_data

补充

label		字段名
error_messages  自定义报错信息
initial  默认值
required  控制字段是否必填
"""
1.字段没有样式
2.针对不同类型的input如何修改
	text
	password
	date
	radio
	checkbox
	...
"""
widget=forms.widgets.PasswordInput(attrs={'class':'form-control c1 c2'})
# 多个属性值的话 直接空格隔开即可

# 第一道关卡里面还支持正则校验
validators=[
            RegexValidator(r'^[0-9]+$', '请输入数字'),
            RegexValidator(r'^159[0-9]+$', '数字必须以159开头')
        ]

其他渲染类型

# 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()
    )
    # 多选
    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()
    )
posted @ 2020-06-04 18:44  小子,你摊上事了  阅读(93)  评论(0编辑  收藏  举报