13、form组件

一、form前戏

这里抛出一个问题,我们写一个注册功能的时候,获取用户数据和密码,利用form表单来提交数据。
然后我们在后端需要判断用户名和密码是否符合一定的条件,比如说用户提交的用户名不能包含一些敏感词汇,否则不符合社会主义核心价值观,密码不能少于三位数,否则提示用户密码太短。

首先我们直接纯手写一个吧,先把HTML页面搭出来

<body>

<form action="" method="post">
<p>
<label>
    用户
    <input type="text" name="username">
    <span style="color: red">{{ back_dic.username }}</span>
</label>
    </p>

<p>
<label>
    密码
    <input type="text" name="password">
    <span style="color: red">{{ back_dic.password }}</span>
</label>
    </p>
    <input type="submit" class="btn btn-info">
</form>

</body>
</html>

后端视图层代码如下

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

我们上面这段自己写的代码干了以下几件事

1.搭建前端HTML页面(渲染页面)
2.后端获取前端数据进行校验(校验数据)
3.对不符合要求的数据进行前端页面的展示 (展示错误信息)

二、form组件书写

现在有一个东西可以帮助我们完成这三个功能,那就是form组件
我们先要在视图层导入以下代码

from django import forms


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

三、form组件校验数据

如何校验数据,可以在Python控制台进行测试

from app01 import views
# 1.给自定义的类传一个字典
obj1 = views.MyForm({'username':'poco','password':'1234','email':'123'})
# 2.判断数据是否全部合法
obj1.is_valid()  # 只有数据全部符合要求才会是True,很显然,结果肯定是false,邮箱格式不对

# 3.查看符合校验规则的数据
obj1.cleaned_data
# 结果:{'username': 'poco', 'password': '1234'}

# 4.查看不符合条件的数据以及不符合的原因是什么
obj1.errors
# 结果:{'email': ['Enter a valid email address.']}
            
# 5.校验数据的时候,默认情况下类里面所有的字段都必须传值
obj2 = views.MyForm({'username':'wendy','password':'123'})
obj2.is_valid()
# 结果:False
obj2.errors
# 结果:{'email': ['This field is required.']}

# 6.默认情况下可以多传,但是绝对不能少传
obj3 = views.MyForm({'username':'jason','password':'1233','email':'123@qq.com','age':'22'})
obj3.is_valid()
# 结果: True

四、form渲染HTML页面

首先后端代码

def ab_form(request):
    # 1.先产生一个空对象
    form_obj = MyForm()
    # 2.直接将该空对象传递给HTML页面
    return render(request, 'ab_form.html', locals())

1、第一种渲染方式

前端代码,这种渲染方式代码书写少,但封装程度高,不便于后续拓展,一般只用于本地测试

<form action="" method="post">
    <p>第一种渲染方式</p>
    {{ form_obj.as_p }}

{#    {{ form_obj.as_ul }}#}
{#    {{ form_obj.as_table }}#}
</form>

我们前端并没有写input输入框的标签,但页面已经有了。这些 输入框的名字都是取决于你后端书写的那个类。

2、第二种渲染方式

通过对象.username的方式渲染输入框,又可以通过.label又可以拿到名字。这个名字还可以通过后端的类代码来自定义名字

class MyForm(forms.Form):
 username = forms.CharField(min_length=3, max_length=8,label='用户名')

这种方式扩展性高,但是需要手写大量代码,所以也不推荐。

<form action="" method="post">
    <p>第二种渲染方式</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>
</form>

我们知道用.xxx的方式其实

3、第三章渲染方式(推荐)

代码书写简单,并且扩展性高

<form action="" method="post">    <p>第三种渲染方式</p>    {% for form in form_obj %}    <p>{{ form.label }}{{ form }}</p>】    {% endfor %}</form>

五、form展示提示信息

首先我们要把前端对我们做的校验取消掉,也就是浏览器,他会自动帮你做校验,如果你设置了最长的用户名为8位,这时候你是不能输入超越8位的字符的,会直接卡在那里,所以我们要取消前端帮我们做的校验,只需要在form表单中添加一个参数novalidate就可以了。

<form action="" method="post" novalidate>    {% for form in form_obj %}    <p>        {{ form.label }}{{ form }}        <span style="color: red">{{ form.errors.0 }}</span>    </p>    {% endfor %}    <input type="submit"></form>

后端

def ab_form(request):    # 1.先产生一个空对象    form_obj = MyForm()    if request.method == 'POST':        # 获取用户数据并校验        form_obj = MyForm(request.POST)        # 判断数据是否违规        if form_obj.is_valid():            # 不违规,存储数据            pass        else:            # 违规,展示给前端            pass    # 2.直接将该空对象传递给HTML页面    return render(request, 'ab_form.html', locals())# 这里错误信息显示的都是英文,如何变成中文。找到当初写form组件的那个类,写以下几个参数class MyForm(forms.Form):    # username字段是字符串类型,最小3位,最大8位    username = forms.CharField(min_length=3, max_length=8, label='用户名',                               error_messages={                                   'min_length': '用户名最少3位',                                   'max_length': '用户名至少8位',                                   'required': '密码不能为空'})    # password字段是字符串类型,最小3位,最大8位    password = forms.CharField(min_length=3, max_length=8)    # email字段必须符合邮箱格式(@xx.com)    email = forms.EmailField()

六、forms组件钩子函数

钩子函数(HOOK),是一种在特定的节点自动触发完成响应的操作,钩子函数就是第二道关卡,能够让我们自定义校验规则

在forms组件中有两类钩子
1.局部钩子:给单个字段增加校验规则
2.全局钩子:给多个字段增加校验规则

 # 针对单个字段的  使用局部钩子  	eg:用户名不能有xxx
def clean_username(self):
	# 对象里有cleaned_data这个属性,拿到了里面的username来看一下
    username = self.cleaned_data.get('username')
    if 'xxx' in username:
		# 提示前端展示错误信息
		self.add_error('username','xxx是敏感词汇,不能使用!')
	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组件其他参数以及补充知识点

label		字段名
error_messages	自定义报错信息
initial		默认值
required	控制字段是否必填

# 如何改变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'})

posted @ 2021-06-13 18:21  黑影Poco  阅读(51)  评论(0)    收藏  举报