Form表单验证本质:
- 就是一个类class MyForm(forms.Form) 继承了forms.Form
form组件的主要功能如下:
- 生成页面可用的HTML标签
- 对用户提交的数据进行校验
- 保留上次输入内容
使用form组件添加用户信息的功能
# 自定义Form类
from django import forms
class UserInfoForm(Form):
# 表单的字段名字最好和model的字段名字一致,方便操作
username = forms.CharField(
min_length=5,
max_length=32,
error_messages={
'required':'不能为空',
'min_length':'最短5个字符',
'max_length':'最长32的字符'
},
label="用户名",
)
pwd = forms.CharField(
min_length=6,
# Form表单默认生成<input type='text'/> 标签 如果要修改可以使用widgets组件 或者 填写 attr属性
# widget=widgets.PasswordInput()
widget=widgets.TextInput(attrs={'type': 'password'})
)
#------ 生成select标签的两种形式 -----
# 第一种后台接受到的数据是整数{'city_id': 1}
city_id = forms.IntegerField(
widget=widgets.Select(
choices=[(1,'北京'),(2,'天津'),(3,'上海')], # 可以添加option标签 接受列表格式的数据 每个元组对应value 和 text文本
attrs = {'id': '001', 'class':'cls-01','diy':'自定义'} # 可以设置属性值 添加id class 名 自定义属性
)
)
# 第二种接受的数据是字符串{'hobby': '1'}
hobby = forms.ChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
label="爱好",
initial=3,
widget=forms.widgets.Select()
)
# html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户注册</title>
</head>
<body>
<h1>用户信息注册</h1>
<form method="POST" action="/add_userinfo.html">
{% csrf_token %}
<p>
{{ userinfo_form.username }}{{ login_form.username.errors.0 }}
</p>
<p>
{{ userinfo_form.pwd }}{{ userinfo_form.pwd.errors.0 }}
</p>
<p>
{{ userinfo_form.city_id }}{{userinfo_form.city_id.errors.0 }}
</p>
<p>
{{ userinfo_form.hobby }}{{ userinfo_form.hobby.errors.0 }}
</p>
<input type="submit" value="提交" />
</form>
</body>
</html>
# view.py
def userinfo(request):
if request.method == 'GET':
userinfo_form = UserInfoForm()
return render(request, 'userinfo.html', {'userinfo_form': userinfo_form})
else:
userinfo_form = UserInfoForm(request.POST)
# 校验数据的有效性 成功则向数据库添加数据
if userinfo_form.is_valid():
models.UserInfo.objects.create(**userinfo_form.cleaned_data)
return redirect('/userinfo.html')
else:
#失败则将用户提交的表单数据和表单html再次返回给用户
return render(request, 'userinfo.html', {'userinfo_form': userinfo_form})
Form表单字段的参数:
# 参数分为2大类
# Field(
# 1. 数据校验
# required=True, 不可以为空,默认可以不写
# error_messages=None, 设置错误信息dict格式{'required':'不能为空','min_length':'长度最小是5'}
# validators=(), 自定义正则规则,传入一个列表, 可以传入多个规则 也可以传入函数 def 函数名(value):pass
# 2. 自动生成html标(除了widget,其他不建议使用)
# widget=None, 自定义显示在前端的表单控件
# initial 默认显示的值
# label=None,
# help_text='',
# show_hidden_initial=False,
# localize=False,
# disabled=False,
# label_suffix=None
# )
Form表单的所有内置字段:
Field
required=True 是否运行为空
widget=None, HTML插件
label=None, 用于生成label标签或显示内容
initial=None, 初始值
help_text=' ', 帮助信息(在标签旁显示)
error_messages=None 错误信息{'required': '不能为空', 'invalid': '格式错误'}
validators=[] 自定义验证规则
localize=False, 是否支持本地化
disabled=False, 是否可以编辑
label_suffix=None Label内容后缀
CharField(Field)
max_length=None 最大长度
min_length=None 最小长度
strip=True 是否移除用户输入空白
IntegerField(Field)
max_value=None, 最大值
min_value=None, 最小值
DecimalField(IntegerField)
max_value=None, 最大值
min_value=None, 最小值
max_digits=None, 总长度
decimal_places=None, 小数位长度
BaseTemporalField(Field)
input_formats=None 时间格式化
DateField(BaseTemporalField) 格式:2015-09-01
TimeField(BaseTemporalField) 格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
RegexField(CharField)
regex, 自定制正则表达式
max_length=None, 最大长度
min_length=None, 最小长度
error_message=None, 忽略,错误信息使用 error_messages={'invalid': '...'}
FileField(Field)
allow_empty_file=False 是否允许空文件
ImageField(FileField)
...
注:需要PIL模块,pip3 install Pillow
以上两个字典使用时,需要注意两点:
- form表单中 enctype="multipart/form-data"
- view函数中 obj = MyForm(request.POST, request.FILES)
ChoiceField(Field)
choices=(), 选项,如:choices = ((0,'上海'),(1,'北京'),)
required=True, 是否必填
widget=None, 插件,默认select插件
label=None, Label内容
initial=None, 初始值
help_text='', 帮助提示
ModelChoiceField(ChoiceField)
... django.forms.models.ModelChoiceField
queryset, # 查询数据库中的数据
empty_label="---------", # 默认空显示内容
to_field_name=None, # HTML中value的值对应的字段
limit_choices_to=None # ModelForm中对queryset二次筛选
ModelMultipleChoiceField(ModelChoiceField)
... django.forms.models.ModelMultipleChoiceField
TypedChoiceField(ChoiceField)
coerce = lambda val: val 对选中的值进行一次转换
empty_value= '' 空值的默认值
TypedMultipleChoiceField(MultipleChoiceField)
coerce = lambda val: val 对选中的每一个值进行一次转换
empty_value= '' 空值的默认值
FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹
required=True,
widget=None,
label=None,
initial=None,
help_text=''
GenericIPAddressField
protocol='both', both,ipv4,ipv6支持的IP格式
unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
SlugField(CharField) 数字,字母,下划线,减号(连字符)
UUIDField(CharField) uuid类型
Django Form内置字段
默认生成的html标签样式:
CharField --> input标签 <input type="text" />
ChoiceFiled --> select标签 <select></select>
如果需要修改标签类型,需要使用widget参数
initial
设置初始值的两种方式:
# 一、在Form表单字段中设置初始值
class UserInfoForm(Form):
# 表单的字段名字最好和model的字段名字一致,方便操作
username = fields.CharField(
min_length=5,
max_length=32,
initial='我是在html上首次显示的初始值' # 设置初始值
)
...
# 二、实例化Form类时设置初始值
def test(request):
userinfo_form = UserInfoForm(initial={'字段名1': '初始值1','字段名2': '初始值2'})
return render(request, 'userinfo.html', {'userinfo_form':userinfo_form})
自定义错误信息 error_messages
class UserInfoForm(Form):
username = fields.CharField(
min_length=5,
max_length=32,
error_messages={
'required':'不能为空',
'min_length':'最短5个字符',
'max_length':'最长32的字符'
}
)
给Form指定字段的标签添加属性
city_id = fields.IntegerField(
widget=widgets.Select(
choices=[(1,'北京'),(2,'天津'),(3,'上海'),(4,"武汉")], # 可以添加option标签 接受列表格式的数据 每个元组对应value 和 text文本
attrs = {'id': '001', 'class':'cls-01','diy':'自定义'} # 可以设置属性值 添加id class 名 自定义属性
)
)
使用内置字段 forms.RegexField 和参数 validators 自定义验证规则
forms.RegexField
phone = forms.RegexField(r'^1[35678]\d{9}$', max_length=11)
validators
phone = forms.CharField(
min_length=11,
max_length=11,
validators=[RegexValidator(r'^1[345678]\d{9}$', '手机号格式不正确'), RegexValidator(),...] # 可以传入多个规则
)
还可以自定义校验函数传入 validators
# 自定义校验函数
def phone_validate(value):
# 拿用户填写的手机号去数据库中校验
is_exits = models.PhoneInfo.objects.filter(phone=value)
if is_exits:
# 如果手机号被注册,不能再注册
raise ValidationError("该手机号已经被注册")
else:
return value
phone = forms.CharField(
max_length=11,
validators=[RegexValidator(r'^1[345678]\d{9}$', '手机号格式不正确'), phone_validate]
)