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