forms组件进阶
forms组件钩子函数
钩子函数的作用
用于程序的执行过程中设定额外的逻辑
具体用处
校验用户名是否已存在
钩子函数之局部钩子(校验单个字段)
校验密码和确认密码是否一致
钩子函数之全局钩子(校验多个字段)
# 局部钩子:校验用户名是否已存在(一次性只能设定一个字段)
注意:钩子函数是数据经过了字段第一层参数校验之后才会执行
def clean_name(self): # 自动生成的函数名,专门用于对name字段添加额外的校验规则
# 先获取用户名
name = self.cleaned_data.get('name')
# 判断用户名是否已存在
is_exist = models.User.objects.filter(name=name)
if is_exist:
# 提示信息
self.add_error('name', '用户名已存在')
# 最后将获取的name返回回去
return name
# 全局钩子:校验密码与确认密码是否一致(次性只能设定多个字段)
def clean(self):
# 获取多个字段数据
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
if not password == confirm_password:
self.add_error('confirm_password', '两次密码不一致')
# 最后将整个数据返回
return self.cleaned_data
forms组件字段参数
forms组件字段类型
min_value 最小值
max_value 最大值
min_length 最小长度
max_length 最大长度
initial 默认值
regvalidators 正则校验器
label 字段名称
error_messages 错误提示
# regvalidators具体用法
phone = forms.CharField(label='手机号',
validators=[
RegexValidator(r'^[0-9]+$', '请输入数字'),
RegexValidator(r'0?(13|14|15|17|18|19)[0-9]{9}', '手机号必须位13、14、15、17、18、19开头')],
error_messages={
'required': '手机号不能为空'
},
widget=forms.widgets.TextInput(attrs={'class': 'form-control'})
)
# choices具体用法
选择类型的标签内部对应关系
hobby = forms.MultipleChoiceField(
choices=((1, "游泳"), (2, "跑步"), (3, "睡觉"),(4, "看星星")
) # 可直接编写
def __init__(self, *args, **kwargs): # 也可从数据库中获取
super(MyForm,self).__init__(*args, **kwargs)
self.fields['hobby'].choices = models.User.objects.all().values_list('id','caption')
forms组件源码分析
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=None,
empty_permitted=False, field_order=None, use_required_attribute=None, renderer=None):
self.is_bound = data is not None or files is not None
# 查看类源码发现只要给类传参self.is_bound肯定是True
def is_valid(self):
return self.is_bound and not self.errors
# 查看类源码发现只有给类传参并且self.errors为False时is_valid的返回值才为True
@property
def errors(self):
if self._errors is None:
self.full_clean()
return self._errors
# 查看源码发现self._errors初始化就是None,所以肯定会调用full_clean方法
from django.core.exceptions import ValidationError
raise ValidationError('用户名已存在')
# 查看源码发现校验数据的整个过程内部都有异常处理机制
modelform
forms组件主要配合models里面的某些类一起使用,但一些类里面的字段需要在forms类中重写一遍造成代码冗余
为了解决代码冗余产生了ModelForm(基于forms组件)
class MyUser(forms.ModelForm):
class Meta:
model = models.User # 指定关联的表
fields = '__all__' # 所有的字段全部生成对应的forms字段
labels = {
'name': '用户名',
'age': '年龄',
'addr': '地址',
'email': '邮箱'
}
widgets = {
"name": forms.widgets.TextInput(attrs={"class": "form-control"}),
}
def reg(request):
form_obj = MyUser()
if request.method == 'POST':
form_obj = MyUser(request.POST)
if form_obj.is_valid():
form_obj.save() # 新增数据
return render(request, 'reg.html', locals())