form组件

forms组件引入

  • 需求
写一个注册功能
	获取用户名和密码 利用form表单提交数据
	在后端判断用户名和密码是否符合一定的条件
		用户名中不能含有金瓶
		密码不能少于三位
	
将不符合的提示信息在输入框后面展示
  • 代码实现
# 后端代码
def ab_form(request):
    back_dic = {'username':'','password':''}
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if '金瓶' in username:
            back_dic['username'] = '不符合规范'
        if len(password) < 3:
            back_dic['password'] = '太短了'
    return render(request,'ab_form.html',locals())

# 前端代码
<body>
<form action="" method="post">
    <p>
        username:<input type="text" name="username">
        <span style="color: red">{{ back_dic.username }}</span>
    </p>
    <p>
        password:<input type="text" name="password">
        <span style="color: red">{{ back_dic.password }}</span>
    </p>
    <input type="submit" class="btn btn-info">
</form>
</body>
  • 分析
1.手动书写前端获取用户数据的html代码						渲染html代码
2.后端对用户数据进行校验								   校验数据
3.对不符合要求的数据进行前端提示						     展示提示信息

forms组件基本使用

介绍

在上面forms组件引入中,自己写了代码校验用户输入是否符合某一个标准,页面也是手动渲染的,对不符合要求的数据的提示也是自己来判断的。
forms组件的作用就是可以不需要手动实现以上三个需求!!!

基本使用

from django import forms
class MyForm(forms.Form):
    # username字符串类型,最小3位,最大8位
    username = forms.CharField(max_length=8,min_length=3)
    # password,字符串类型,最小3位,最大8位
    password = forms.CharField(max_length=8,min_length=3)
    # email字段必须符合邮箱格式
    email = forms.EmailField()

校验数据(是否符合参数的设定)

  • 测试环境准备
- 方式一:通过test.py文件进行测试
- 方式二:pycharm中准备好的测试环境,Python console
  • 使用方式二进行测试
# 1 首先导入需要测试的文件
from app01 import views

# 2 将校验数据组织成字典的形式传入自定义的类进行校验
form_obj = views.MyForm({'username':'chloe','password':'1026','emali':'123'})

# 3 判断数据是否合法:注意该方法只有在所有的数据全部合法的情况下才会返回True
form_obj.is_valid()  # False

# 4 查看所有校验通过的数据
form_obj.cleaned_data
{'username':'chloe','password':'1026'}

# 5 查看所有不符合校验规则的字段以及不符合的原因
form_obj.errors()
{
  'email': ['Enter a valid email address.']
},这里结果的值是一个列表,原因是校验条件可能有多个都不符合

# 6如果校验数据中出现了类中没有的字段,forms组件只会校验存在的字段,不存在的字段传了直接忽略
form_obj = views.MyForm({'username':'chloe','password':'1026','emali':'123@qqcom','hobby':'read'})
form_obj.is_valid()  # True

# 7 默认情况下,类里面所有的字段都必须传值,也就意味着校验数据的时候,默认情况下数据可以多传但是不能少传
form_obj = views.MyForm({'username':'jason','password':'123'})
form_obj.is_valid()
False

渲染标签

form组件会自动帮忙渲染获取用户输入的标签(input select radio checkbox),但是不能自动渲染提交按钮

- 后端代码
def index(request):
    # 1 先产生一个空对象
    form_obj = MyForm()
    
    if request.method == 'POST':
        # 3 获取用户数据进行校验,如果一条一条的获取用户数据太过繁琐,而且校验数据需要字典格式,而request.POST获取到的数据格式就是queryset——dict对象
        form_obj = MyForm(request.POST)
        # 4 如果数据合法应该操作数据库,这里先简写
        if form_obj.is_valid():
            return HttpResponse('OK')
        # 5 如果数据不合法,就需要将错误信息展示到前端
        # 问题:如何展示到前端呢?因为form校验产生的错误信息就是字典格式,到前端就是自定义对象,所以可以通过前端点点点的方式
        
    # 2 直接将空对象传递给html页面
    return render(request,'index.html',locals())


- 前端代码
<body>
<form action="" method="post" novalidate>
    <p>第一种渲染方式:代码数学极少,封装程度太高,扩展性不好</p>
{#    {{ form_obj.as_p }}#}
{#    {{ form_obj.as_ul }}#}
{#    {{ form_obj.as_table }}#}
    <p>第二种渲染方式:扩展性性很强,但是需要书写的代码太多</p>
{#    {{ form_obj.username.label }}{{ form_obj.username }}#}
{#    {{ form_obj.password.label }}{{ form_obj.password }}#}
{#    {{ form_obj.email.label }}{{ form_obj.email }}#}
    <p>第三种渲染方式:推荐使用,代码精简,并且扩展性也很高</p>
    {% for form in form_obj %}
        <p>
            {{ form.label }}{{ form }}
        // form.errors.0的意思是只展示第一条错误提示,否则forms组件会将错误信息展示成无序列表的形式
        <span style="color: red">{{ form.errors.0 }}</span>
        </p>

    {% endfor %}

    <input type="submit" class="btn btn-info">
</form>
</form>
</body>

HOOK钩子函数

简介

在特定的节点自动触发完成相应操作,写在类中

钩子函数在forms组件中就类似与第二道关卡,能够自定义校验规则

在forms组件中有两类钩子

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

案例

  • 校验用户名中不能含有666 只是校验username字段 局部钩子
  • 校验密码和确认密码是否一致 password confirm两个字段 全局钩子
# 钩子函数
# 局部钩子
def clean_username(self):
    # 获取到用户名
    username = self.cleaned_data.get('username')
    if '666' in username:
        # 前端展示错误信息
        self.add_error(field='username',error='666不行')
    # 将钩子函数钩取出来的数据再放回去
    return username
# 全局钩子
def clean(self):
    password = self.cleaned_data.get('password')
    cof_password = self.cleaned_data.get('confirm_password')
    if not cof_password == password:
        self.add_error('confirm_password','两次密码不一致')
    return self.cleaned_data

forms组件其他参数及补充知识点

参数补充

  • lable字段名
  • error_messages 自定义报错信息
username = forms.CharField(min_length=3,max_length=8,label='用户名',error_messages={
    'min_length':'最少三位',
    'max_length':'最多八位',
    'required':'不能为空',
})
  • initial 默认值

  • required 控制字段是否必填

字段的样式修改

forms组件默认没有使用bootstrap的样式,如何使用呢?针对不同类型的input框(text password date等)如何修改呢
  • 针对input标签的属性值
widget=forms.widgets.PasswordInput(attrs={'class':'form-control c1 c2'})
# 多个属性值的话 直接空格隔开即可
  • 第一道关卡里面还支持正则校验
validators=[
            RegexValidator(r'^[0-9]+$', '请输入数字'),
            RegexValidator(r'^159[0-9]+$', '数字必须以159开头')
        ]
  • input框其他类型渲染
# 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 19:46  微信搜索-程序媛小庄  阅读(192)  评论(0编辑  收藏  举报