1.Form组件功能
1.1生成标签
生成HTML标签和携带数据,保留原来提交的数据,刷新时不会刷掉输入值,显示默认值
1.2数据校验和流程
1.2.1 每个字段的内部的校验如require+validators+max_length之类的,
1.2.2 对每个字段的钩子方法进行校验
def clean_字段名(self):
pass
1.2.3对所有值进行校验
def clean(self):
print(self.cleaned_data)
def _post_clean(self):
pass
校验失败:self.errors['__all__'] = 错误
1.2.4 校验成功
self.cleaded['字段'] = 值
1.2.5 校验失败
self.errors['字段'] = 错误
如果想要让某个错误信息,展示在特定的字段旁,就可以使用:form.add_error("password", "用户名或密码错误")
2.使用
2.1在Django的视图函数使用
views.py
from django import forms
from django.core.validators import RegexValidator
class Login(forms.Form):
# 生成选择标签
choices = forms.ChoiceField(
label='角色' # 标签名
required=True, # 不能为空
choices=(('1','客户'),('2','管理员')), # 选项内容
widget=forms.Select(attrs={'class':'form-control'}) # 设置标签样式
)
# 生成文本输入框
username = forms.CharField(
label='用户名' # 标签名
initial='username1', # 预填充表单字段和重用表单数据
required=True,
正则表达式,
widget = forms.TextInput(attrs={'class':'form-control','placeholder':'用户名'})
)
password=forms.CharField(
label='密码',
min_length=6, 最小长度为6
max_length=16,最大长度16
validators=[RegexValidator(r'^[a-zA-Z0-9]+$', '只允许使用字母数字字符')],# 正则表达式
widget = forms.TextInput(attrs={'class':'form-control','placeholder':'密码'})
)
# 实例化使用
form = Login(initial={'username':'xxx','password':"xxx"})
2.2 在模板中使用
index.html
<div>
{{% for field in form %}}
使用标签
{{field.label}}
使用字段
{{field}}
展示错误信息
{{field.error.0}}
{{% endfor %}}
</div>
3.整体校验流程
① is_valid()
第一步form.is_valid()后第一步会进行字段清理,is_valid() 方法在表单实例化时也可 以传递 data 参数,例如 form = Login(data=request.POST),这样可以处理 POST 请求中的数据。通过clean()方法来清理每个字段的数据第二步会调用每个字段的validate()方法, 如果有validate属性的话,最后会调用表单的full_clean()方法,这个方法会触发clean()方法,如果 所有的验证都通过了,is_valid() 会返回 True,否则返回 False。如果返回 False,以通过 form.errors 属性来访问错误信息。
② form.errors
第二步form.errors() form.errors类似一个字典对象,包含了表单验证过程中所有的 错误信息,每个字段的错误信息可以通过字段名作为键来访问,如果form.is_valid() 返回False,form.errors将包含错误的信息。
③ full_clean()
第三步form.full_clean()会进行清理字段,并对每个字段调用clean方法,字段验证: 对于每个字段,它会检查是否有 required 属性,并且确保字段值不为空。然后, 它会调用字段的 validate() 方法,如果字段有 validators 属性的话,ull_clean() 方法会调用表单的 clean() 方法,这个方法可以被重写以添加表单级别的验证逻辑。此外, 它还会调用 clean_() 方法,如果这样的方法存在的话,用于特定字段的验证, full_clean() 方法在 is_valid() 内部调用,但也可以单独调用,用于在不渲染表单的情况下执行完整的验证过程。
2.ModelForm组件功能
和Form组件对比,优势在于
2.1 不用编写字段,直接引用model字段
class TestModelForm(froms.ModelForm):
class Meta:
model=model.xxx # 指定表
fields = "__all__" # 展示全部字段
fields = ['title','percent',] # 自定义选择字段
exclued = ['active'] # 展示除了active的其他字段
2.2 生成html标签 + 插件 + 参数的配置
class TestModelForm(froms.ModelForm):
class Meta:
model=model.xxx
fields = ['title','price']
widgets = {
'title':forms.PasswordInput(render_value=True)
}
2.3 表单的验证
class TestModelForm(froms.ModelForm):
title = forms.CharField(validators=[])
class Meta:
model = model.xxx
fields = ['name','title']
def clean_title(self):
value = self.cleaned_data['title']
return title
2.4 保存(ORM保存)
form = TestModelForm(data=request.POST)
form.save()
2.5 补充
如果不想重复的对字段进行样式设置,可以利用类的继承特性(类的MRO)和super关键字进行统一设置
2.5.1 例如统一对输入框字段进行bootstrap样式设定
class BootStrapForm:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# {'title':对象,"percent":对象}
for name, field in self.fields.items():
# bootstrap的输入框样式 class=form-control
field.widget.attrs['class'] = "form-control"
# 输入提示
field.widget.attrs['placeholder'] = "请输入{}".format(field.label)
class LevelForm(BootStrapForm, forms.Form):
title = forms.CharField(
label="标题",
required=True,
)
percent = forms.CharField(
label="折扣",
required=True,
)
以上代码利用类的继承关系(MRO)来进行 先继承BootStrapForm,BootStrapForm在初始化时,会同时进行super(父类)的初始化,会按照MRO来进行,BootStrapForm没有找到self.fields.items()时,会按照MRO来进行,就是BootStrapForm->forms.Form,从而在forms.From里找到self.fields.items,进行样式设置。