小谈Django中的form组件
form
简单Form示例
定义
from django import forms
class RegForm(forms.Form):
user = forms.CharField(label="账号")
pwd = forms.CharField(label="密码", widget=forms.PasswordInput)
使用
视图函数
def reg(request):
form_obj = RegForm()
if request.method == 'POST':
form_obj = RegForm(request.POST)
if form_obj.is_valid():
print(request.POST)
# 上面的显示结果:
# <QueryDict: {'csrfmiddlewaretoken': ['wFp3cnKRpV1ZMuOdZl0rklwWkncSfULWeWaDPhaBa9eObp0Vnl4JBgZqj7MJuy4t'], 'user': ['alex'], 'pwd': ['123']}>
print(form_obj.cleaned_data, type(form_obj.cleaned_data))
# 上面的显示结果:
# {'user': 'alex', 'pwd': '123'} <class 'dict'>
return HttpResponse('注册成功')
return render(request, 'reg.html', {'form_obj': form_obj})
模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post" novalidate>
{% csrf_token %}
{# {{ form_obj.as_p }}#}
<p>
<label for="{{ form_obj.user.id_for_label }}">{{ form_obj.user.label }}</label>
{{ form_obj.user }} <span>{{ form_obj.user.errors.0 }}</span>
</p>
<p>
<label for="{{ form_obj.pwd.id_for_label }}">{{ form_obj.pwd.label }}</label>
{{ form_obj.pwd }}
</p>
{{ form_obj.errors }}
<button>注册</button>
</form>
</body>
</html>
模板更多
- forms.Charfield --> 字段对象
- widget --> 插件对象
生成所有字段的input框
{{ form_obj.as_p }}
生成某个字段的input框
{{ form_obj.user }}
某个字段的中文提示
{{ form_obj.user.label }}
某个字段的input框的ID
{{ form_obj.user.id_for_label }}
生成单个的input框并且设置label标签
<p>
<label for="{{ form_obj.user.id_for_label }}">{{ form_obj.user.label }}</label>
{{ form_obj.user }}
</p>
<label for="{{ form_obj.user.id_for_label }}"> -> 作用: 让input框聚焦 -> 鼠标点击"账号"光标自动切到input框中
所有字段的校验错误
{{ form_obj.errors }} -> 所有字段的所有错误
{{ form_obj.errors.0 }} -> 所有字段的第一个错误
某个字段的校验错误
{{ form_obj.user.errors }} -> 某个字段的所有错误
{{ form_obj.user.errors.0 }} -> 某个字段的第一个错误
widget=forms.PasswordInput
# input框显示密文
class RegForm(forms.Form)L
...
pwd = forms.CharField(label='密码', widget=forms.PasswordInput)
Form常用字段和插件
- 字段用于对用户请求数据的验证 __> 与form表单校验相关
- 插件用于自动生成HTML __> 和前段渲染相关
所有字段
# 导入forms模块语句:
# from django import forms
# 直接点进forms有下面这句, 然后点进去fields看
from django.forms.fields import *
# 看到所有的字段:
__all__ = (
'Field', 'CharField', 'IntegerField',
'DateField', 'TimeField', 'DateTimeField', 'DurationField',
'RegexField', 'EmailField', 'FileField', 'ImageField', 'URLField',
'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField',
'ComboField', 'MultiValueField', 'FloatField', 'DecimalField',
'SplitDateTimeField', 'GenericIPAddressField', 'FilePathField',
'SlugField', 'TypedChoiceField', 'TypedMultipleChoiceField', 'UUIDField',
)
常用字段只写了三个 ; 如果样式不够 , 可以修改widget就可以了 , 可以点出很多东西
- 比如ChoiceField(widget=forms.RadioSelect)
- 比如MultipleChoiceField(widget=forms.CheckboxSelectMultiple)
Charfield
user = forms.CharField(label="账号")
ChoiceField
gender = forms.ChoiceField(choices=(('1','男'),('2','女')),label='性别')
MultipleChoiceField
hobby = forms.MultipleChoiceField(choices=(('1','抽烟'),('2','喝酒'),('3','吐口水')), label='爱好')
inital
class RegForm(forms.Form):
gender = forms.ChoiceField(choices=(('1','男'),('2','女')),label='性别', initial='2') # 设置默认值, 渲染在前段页面就是input框中value的值
error_messages
class RegForm(forms.Form):
user = forms.CharField(
label="账号",
min_length=6,
# 在前段显示错误的信息; 如果不设置, 显示的是默认的,英文的
error_messages={
'required': '不能为空!',
'min_length':'至少是6位!'
}
)
widget
# 前段的input框显示密文
class RegForm(forms.Form)L
...
pwd = forms.CharField(label='密码', widget=forms.PasswordInput)
# widget=forms.PasswordInput
# 上下两个一样,主要看点进去"from django import forms"中的forms,看模块如何导入的.
# widget=forms.widgets.PasswordInput
required
class RegForm(forms.Form):
user = forms.CharField(
# required默认是True_>必填的;改成False可以不填
required=False,
label="账号",
min_length=6,
# 在前段显示错误的信息; 如果不设置, 显示的是默认的,英文的
error_messages={
'required': '不能为空!',
'min_length':'至少是6位!'
}
)
disabled
是否禁用
min_length
最小长度
choices
可选择的数据
方法一 :
class RegForm(forms.Form):
...
gender = forms.ChoiceField(choices=(('1','男'),('2','女')),label='性别', initial='2')
hobby = forms.MultipleChoiceField(choices=(('1','抽烟'),('2','喝酒'),('3','吐口水')), label='爱好')
方法二 :
class RegForm(forms.Form):
...
gender = forms.ChoiceField(label='性别', initial='2')
def __init__(self, *args, **kwargs):
super(RegForm, self).__init__(*args, **kwargs)
# self.fields['gender'].choices = [('1','男'),('2','女')]
# 上下两句效果一样, 但是models中gender类得添加双下str方法
self.fields['gender'].choices = models.gender.objects.all()
校验
1. 自带的校验规则
各个字段都有自己自带的校验规则 , 比如required...
2. 自定义校验规则
1. 写函数
from django import forms
from django.core.exceptions import ValidationError
# value就是input框中填写的值
def check_name(value):
# 自定义校验规则
# 如果校验合格, 什么都不做;
# 如果校验不合格, 抛出异常(ValidationError)
if 'alex' in value:
raise ValidationError('不能包含alex,非法字符!')
class RegForm(forms.Form):
user = forms.CharField(
label="账号",
min_length=6,
# 自定义校验规则
validators=[check_name]
error_messages={
'required': '不能为空!',
'min_length':'至少是6位!'
}
)
2. 内置校验器
from django import forms
# RegexValidator是正则的内置校验器,还有很多其他的, 比如: 邮箱的,url的,ipv6的,...;可以点进去看
from django.core.validators import RegexValidator
class RegForm(forms.Form):
phone = forms.Charfield(
# RegexValidator()实例化一个RegexValidator的对象,第一个参数是正则表达式; 第二个参数是错误信息;
# 可以点进去看看, 还有其他的,一般这两个就够了
validators=[RegexValidator(r'^1[3-9]\d{9}$', '手机号格式不正确')]
)
3. 局部钩子
class RegForm(forms.Form):
user = forms.CharField(
label="账号",
min_length=6,
error_messages={
'required': '不能为空!',
'min_length':'至少是6位!'
}
)
def clean_user(self):
# 局部钩子 clean_字段名
# 如果校验成功, 返回当前字段的值;
# 如果校验不成功, 抛出异常;
if 'alex' in self.cleaned_data.get('user'):
raise ValidationError('不能包含alex,非法字符!')
return self.cleaned_data.get('user')
4. 全局钩子
class RegForm(forms.Form):
pwd = forms.CharField(label="密码", widget=forms.PasswordInput)
re_pwd = forms.CharField(label="密码", widget=forms.PasswordInput)
...
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
else:
# 这样错误信息就在re_pwd后面显示了,不写的话只会在所有字段的所有错误中出现;
self.add_error('re_pwd','两次密码不一致!!!')
raise ValidationError('两次密码不一致!')
- 如果要定义的校验规则只针对于一个字段使用 __> 局部钩子 ;
- 如果要定义的校验规则针对 一个Form中的两个字段合起来做校验( 如密码和确认密码 ) __> 全局钩子 ;
- 如果要定义的校验规则适用于多个字段 __> 写函数或者内置校验器 , 可以只写一次函数 , 然后把函数名写到每个字段的validators中 ;