Form介绍
我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来。
与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否输入,输入的长度和格式等正不正确。如果用户输入的内容有错误就需要在页面上相应的位置显示对应的错误信息.。
Django form组件就实现了上面所述的功能。
form组件的主要功能如下:
- 生成页面可用的HTML标签
- 对用户提交的数据进行校验
- 保留上次输入内容``
使用form组件实现注册功能
先定义一个RegFom类:
from django import forms
# 定义form
class RegForm(forms.Form):
user = forms.CharField(label='用户名:') # 两个字段
pwd = forms.CharField(label='密码:')
再写一个视图函数:
def reg(request):
form_obj = RegForm() # 实例化一个对象
if request.method == 'POST':
# 实例化form对象的时候,把post提交的数据直接传进去
form_obj = RegForm(request.POST)
# 调用form_obj校验数据的方法
if form_obj.is_valid():
return HttpResponse('注册成功!')
# 模板语言
return render(request, 'register.html', {'form_obj': form_obj})
register.html文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
</head>
<body>
<div>
<form action="/reg/" method="post" novalidate autocomplete="off">
{% csrf_token %}
<div>
<label for="{{ form_obj.user.id_for_label }}">{{ form_obj.user.label }}</label>
{{ form_obj.user }} {{ form_obj.user.errors }}
</div>
<div>
<label for="{{ form_obj.pwd.id_for_label }}">{{ form_obj.pwd.label }}</label>
{{ form_obj.pwd }}{{ form_obj.pwd.errors }}
</div>
<div>
<input type="submit" class="btn btn-success" value="注册">
</div>
</form>
</div>
</body>
</html>
视图函数:
def reg(request):
form_obj = RegForm() # 实例化一个对象
if request.method == 'POST':
# 实例化form对象的时候,把post提交的数据直接传进去
form_obj = RegForm(request.POST)
# 调用form_obj校验数据的方法
if form_obj.is_valid():
return HttpResponse('注册成功!')
# 模板语言
return render(request, 'register.html', {'form_obj': form_obj})
看网页效果发现 也验证了form的功能:
- 前端页面是form类的对象生成的 -->生成HTML标签功能
- 当用户名和密码输入为空或输错之后 页面都会提示 -->用户提交校验功能
- 当用户输错之后 再次输入 上次的内容还保留在input框 -->保留上次输入内容
Form那些事
常用字段与插件
创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;
initial
初始值,input框里面的初始值.
# 定义form
class RegForm(forms.Form):
user = forms.CharField(
label='用户名:', # 输入框名称信息
# required=True, # 是否允许为空
min_length=6, # 最短长度设置
initial='tom', # 默认值设置
error_messages={
'required': '账户不能为空',
'invalid': '格式错误',
'min_length': '用户名最短6位'
}
) # 两个字段
pwd = forms.CharField(
label='密码:',
min_length=6,
widget=widgets.PasswordInput(), # 密码隐藏显示
error_messages={
'required': '账户不能为空',
'invalid': '格式错误',
'min_length': '用户名最短6位'
}
)
error_messages 重写错误信息
password widget=widgets.PasswordInput(), # 密码隐藏显示
radioSelect
单radia值为字符串
# 性别字段
gender = forms.fields.ChoiceField(
choices=((1, '男'), (2, '女'), (3, '保密')),
label='性别',
initial=3,
# widget=forms.widgets.RadioSelect() # 是否隐藏选项框
)
单选Select
# 单选爱好
hobby = forms.fields.ChoiceField(
choices=((1, '篮球'), (2, '足球'), (3, '双色球')),
label='爱好:',
initial=3,
widget=forms.widgets.Select()
)
单选Select从数据库取数据并且同时更新数据库方法:
hobby = forms.ChoiceField(
# choices=((1, '篮球'), (2, '足球'), (3, '双色球')),
# 从数据库获取数据
# choices=models.Hobby.objects.all().values_list('id', 'name'), # 元组
# label='爱好:',
# initial=3,
widget=forms.widgets.Select()
)
# 类中执行操作,可以在更新数据的同时,不用更新项目,可以直接显示到前端
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# print(self.fields) # 有序字典
# print(1, self.fields['hobby'].choices)
# 写这个方法之后,直接在数据库更新数据库,不用启动项目,前端也能查到数据
self.fields['hobby'].choices = models.Hobby.objects.all().values_list('id', 'name')
多选Select
# 多选爱好
# hobby2 = forms.fields.ChoiceField(
# choices=((1, '篮球'), (2, '足球'), (3, '双色球')),
# label='爱好2:',
# initial=[1, 3], # 默认多选
# widget=forms.widgets.SelectMultiple() # 多选框设置
# )
校验规则
方式1:
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidator
class MyForm(Form):
user = fields.CharField(
validators=[
RegexValidator(r'^1[3-9]\d{9}$', '手机号不正经') # 手机号提示信息
]
)
方式2:
from django.shortcuts import render, HttpResponse
from django import forms
from django.forms import widgets
from django.core.validators import RegexValidator # 正则的一个类
from app01 import models
from django.core.exceptions import ValidationError # 自定义校验\
# 自定义校验函数
def check_name(value):
if 'tom' in value: # 写入不符合规则的内容
raise ValidationError('不符合规则的用户名')
# 定义form
class RegForm(forms.Form):
user = forms.CharField(
label='用户名:', # 输入框名称信息
# required=True, # 是否允许为空
min_length=6, # 最短长度设置
initial='tom', # 默认值设置
validators=[check_name], # 加自定义校验函数
error_messages={
'required': '账户不能为空',
'invalid': '格式错误',
'min_length': '用户名最短6位'
}
)
自定义校验规则:
validators = [ 校验器1,校验器2 ]
1.
from django.core.validators import RegexValidator
RegexValidator(r'^1[3-9]\d{9}$', '手机号不正经')
2. 自定义函数
from django.core.exceptions import ValidationError
def check_name(value):
if 'alex' in value:
raise ValidationError('提示信息')
钩子函数:
1.局部钩子:
# 局部钩子方法,对当前字段做校
def clean_phone(self): # 某一个方法进行校验
value = self.cleaned_data.get('phone') # 取值
if re.match(r'^1[3-9]\d{9}$', value): # 取值校验
return value # 返回校验后的正确信息
raise ValidationError('手机号不正经') # 校验不正确后抛出提示信息
两次密码校验:
# 局部钩子
def clean_re_pwd(self):
pwd = self.cleaned_data.get('pwd')
re_pwd = self.cleaned_data.get('re_pwd')
if pwd == re_pwd:
return re_pwd
raise ValidationError('两次密码不一样')
2.全局钩子
# 全局钩子函数
def clean(self):
pwd = self.cleaned_data.get('pwd')
re_pwd = self.cleaned_data.get('re_pwd')
if pwd == re_pwd:
return self.cleaned_data
self.add_error('re_pwd', '两次密码不一样')
raise ValidationError('两次密码不一样')