form组件
前戏:编写用户登录功能,并校验数据返回提示信息
自己手写登录校验功能
前端:
<form action="" method="post">
<p>username:
<input type="text" name="username">
<span style="color: red">{{ user_dict.username }}</span>
</p>
<p>password:
<input type="text" name="password">
<span style="color: red">{{ user_dict.password }}</span>
</p>
<input type="submit">
</form>
后端:
def ab_form(request):
if request.method == 'POST':
user_dict = {'username': '', 'password': ''}
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'jason':
user_dict['username'] = '用户名不能是jason'
if password == '123':
user_dict['password'] = '密码不能是123'
return render(request, 'ab_form.html', locals())
# 缺陷:每一个字段的匹配规则都要自己手写,而且如果字段很多很麻烦。前端form表单写起来也很繁琐。
form组件介绍
1.数据校验
支持提前设置好各种校验规则,数据传入之后自动校验
2.渲染页面
支持直接渲染用来获取用户数据的各种标签
3.展示信息:
支持针对不同的校验,失败之后展示不同的提示信息
利用form组件编写用户登录校验
form类的创建
from django import forms
class MyForm(forms.Form):
username = forms.CharField(max_length=8, min_length=3) # 用户名最少3个字符 最多8个字符
age = forms.IntegerField(max_value=150, min_value=0) # 年龄最少0岁 最多150岁
email = forms.EmailField() # 邮箱必须符合邮箱格式(至少要有@符号)
数据校验功能
1.传递待校验的数据
form_obj = views.MyForm({'username': 'jason', 'age': 18, 'email': 'aaa'}) # 邮箱格式不正确
2.判断是否所有的数据都符合校验规则
print(form_obj.is_valid()) # False
3.获取符合校验的数据
print(form_obj.cleaned_data) # {'username': 'jason', 'age': 18}
4.获取不符合校验的数据以及错误原因
print(form_obj.errors) # {'email': ['Enter a valid email address.']}
'''
1.form类中编写的字段校验时默认都是必填的 少传肯定通不过校验
2.校验如果多传了一些字段,则这些字段不参与校验,全程忽略
3.指定参数 required=False 表示该字段可以不传值(即不用传值也能校验通过)
'''
渲染标签功能
先用MyForm实例化一个对象
form_obj = MyForm()
1.方式1:(封装程度高,扩展性差,主要用于快速生成页面本地测试)
{{ form_obj.as_p }}
{{ form_obj.as_table }}
{{ form_obj.as_ul }}
2.方式2:(封装程度低 扩展性好 编写困难)
{{ form_obj.name.lable }}
{{ form_obj.name }}
3.方式3:(推荐使用)
{% for form in form_obj %}
<p>
{{ form.label }}
{{ form }}
</p>
{% endfor %}
'''
类中以外的所有标签都不会自动渲染,需要自己编写
'''
展示提示信息
'''
form类中填写的校验性参数 前端浏览器会识别并自动添加相应的校验操作
但是前端的校验时弱不禁风的 不能指望他!! 真校验害得靠后端
form表单可以取消浏览器自动添加校验功能的操作: novalidate属性
<form action="" method="post" novalidate></form>
'''
前端:
<form action="" method="post" novalidate>
{% for form in form_obj %}
<p>
{{ form.label }}
{{ form }}
{{ form.errors.0 }} # 展示错误信息 固定写法
</p>
{% endfor %}
<input type="submit">
</form>
后端:
def func(request):
form_obj = MyForm()
if request.method == 'POST':
form_obj = MyForm(request.POST)
if form_obj.is_valid():
print(form_obj.cleaned_data)
return render(request,'func.html',locals())
form类重要字段参数
max_length、min_length
max_value、min_value
label 字段注释
error_messages 错误提示信息
required 是否为空(是否不传值也能通过校验)
widget 标签类型、标签属性
initial 默认值
validators 正则校验
钩子函数
提供了自定义的校验方式
钩子函数的含义就是在程序的执行过程中穿插额外的逻辑
from类提供第一层校验(格式校验)钩子函数提供第二层校验(如用户名是否存在...)
'钩子函数在数据经过了字段第一层参数校验之后才会运行'
局部钩子:校验单个字段(用户名是否已存在...)
def clean_name(self):
name = self.cleaned_data.get('name')
res = models.User.objects.filter(name=name).first()
if res:
return self.add_error('name','用户名已存在')
return name
全局钩子:校验多个字段(两次密码是否一致...)
def clean(self):
pwd = self.cleaned_data.get('pwd')
confirm_pwd = self.cleaned_data.get('confirm_pwd')
if not pwd == confirm_pwd:
return self.add_error('confirm_pwd','两次密码不一致')
return self.cleaned_data
ModelForm组件
modelform是form的优化版本 使用更简单 功能更强大
class MyModelForm(forms.ModelForm):
class Meta:
model = models.User
fields = '__all__'
def clean_name(self):
name = self.cleaned_data.get('name')
res = models.User.objects.filter(name=name).first()
if res:
self.add_error('name','用户名已存在')
return name