Form组件
功能:
1.生成页面可用的HTML标签
2.对用户提交的数据进行校验
3.保留上次输入内容
生成标签
views.py写法
views.py:
from django import forms
class MyForm(forms.Form):
# 普通输入框
name = forms.CharField(
label = 'xxx', # 标识
requires = True, # 默认为True,内容不为空
min_length = 6, # 最小长度为6
initial = '默认值', # 默认值
validators=[RegexValidator(r'^aaa','不以aaa开头不给通过'),], # 自定义校验规则 RegexValidator(正则,错误信息); RegexValidator(校验函数,)
help_text = '这里是帮助文本', # 帮助文本
error_messages={'min_length':'太短了,要六位!',}, # 自定义错误信息,字典
widget=forms.widgets.TextInput(), # 插件,改变生成的标签的样式
)
# 密文输入框
password = forms.CharField(
label='密码',
min_length=8,
max_length=12,
widget=forms.widgets.PasswordInput(),
)
# 单选
sex = forms.ChoiceField(
label='性别',
initial=3,
choices=((1,'男'),(2,'女'),(3,'保密')), # 元组
widget=forms.widgets.RadioSelect(),
)
# 单选的下拉框
city = forms.ChoiceField(
label='城市',
initial=3,
choices=((1, '北京'), (2, '上海'), (3, '广州')), # 元组
widget=forms.widgets.Select(),
)
# 多选的下拉框
rapper = forms.MultipleChoiceField(
label='说唱歌手',
choices=((1, '光光'), (2, '法老'), (3, '弹壳')), # 元组
widget=forms.widgets.SelectMultiple(),
)
# 多选的checkbox
hobby = forms.MultipleChoiceField(
label='爱好',
choices=((1, '说唱'), (2, '街舞'), (3, '篮球')), # 元组
widget=forms.widgets.CheckboxSelectMultiple(),
)
# 单选的checkbox(我已阅读/记住我/下次自动登录...)
tip = forms.MultipleChoiceField(
label='我已阅读',
choices=(('True', '已选'), ('False', '不选')),
widget=forms.widgets.CheckboxInput(),
)
# date日期类型
birthday = forms.CharField(
label='生日',
widget=forms.widgets.TextInput(attrs={'type':'date',}), # attrs={} 给标签加属性
)
html写法
<form action="" method="post" novalidate>
{% csrf_token %}
<div>
<label for="">{{ form_obj.name.label }}</label>
{{ form_obj.name }}
{{ form_obj.name.help_text }}
<span style="color: red;font-size: 14px">{{ form_obj.name.errors.0 }}</span> <!-- 把索引为0的li的文本信息提取出来 -->
</div>
<div>
<label for="">{{ form_obj.password.label }}</label>
{{ form_obj.password }}
<span style="color: red;font-size: 14px">{{ form_obj.password.errors.0 }}</span>
</div>
<div>
<label for="">{{ form_obj.sex.label }}</label>
{{ form_obj.sex }}
</div>
<div>
<label for="">{{ form_obj.city.label }}</label>
{{ form_obj.city }}
</div>
<div>
<label for="">{{ form_obj.hobby.label }}</label>
{{ form_obj.hobby }}
</div>
<div>
<label for="">{{ form_obj.rapper.label }}</label>
{{ form_obj.rapper }}
</div>
<div>
<label for="">{{ form_obj.tip.label }}</label>
{{ form_obj.tip }}
</div>
<div>
<label for="">{{ form_obj.birthday.label }}</label>
{{ form_obj.birthday }}
</div>
<input type="submit">
</form>
校验内容
def register(request):
form_obj = RegisterForm()
if request.method == 'GET':
return render(request,'register.html',{'form_obj':form_obj}) # html文件渲染form_obj来生成标签(见上面)
else:
form_obj = RegisterForm(request.POST) # 放入用户输入的数据并创建对象
if form_obj.is_valid(): # 校验 返回 true/false
print(form_obj.cleaned_data) # 打印符合规则的内容
return HttpResponse('注册成功')
else:
print(form_obj.errors) # 打印不符合规则的内容(字段和错误信息)
return render(request,'register.html',{'form_obj':form_obj})
局部钩子和全局钩子
字段中的校验规则满足不了需求,就可以考虑使用钩子,在定义的form类中写如下方法
# 局部钩子(clean_字段名):
def clean_name(self):
value = self.cleaned_data['name']
if 'xx' in value:
raise ValidationError('含有敏感词汇:xx')
else:
return value
# 全局钩子(clean):
def clean(self):
value = self.cleaned_data
p1 = value['password']
p2 = value['r_password']
if p1 == p2:
return value
else:
self.add_error('r_password','两次输入的密码不一致!') # 给某个字段单独添加错误信息
raise ValidationError('两次输入的密码不一致!')
校验执行顺序
for循环逐个校验字段(name,password...),其中每个字段先校验字段内的规则,再校验局部钩子.等全部字段都校验完毕后,才校验全局钩子.
ModelForm组件
通过model的属性自动翻译成form的属性, 来进行form组件的工作
创建类
from django import forms
from django.core.exceptions import ValidationError
class BookModelForm(forms.ModelForm):
# title = forms.CharField(max_length=15,min_length=6) 对自动生成的属性不满意的也可以用form的方式生成覆盖
class Meta:
model = models.Book
field = '__all__'
# field = ['title','price'] 可以指定属性生成,不一定要全部生成
# exclude = ['title'] 也可以排除,让指定属性不生成
labels = { # 定制label
'title':'书名',
'price':'价格',
}
widgets = { # 定制样式
'publishDate':forms.widgets.TextInput(attr={'type':'date'}).
}
error_messages = { # 定制错误信息
'title':{'required':'不能为空!'},
}
# 局部钩子
def clean_title(self):
value = self.cleaned_data.get('title')
if 'xx' in value:
raise ValidationError('含有敏感词汇:xx')
else:
return value
# 全局钩子
def clean(self):
pass
def __init__(self,*args,**kwargs): # 给每个属性添加统一的bootstrap样式
super().__init__(*args,**kwargs)
for field in self.fields.values():
field.widget.attrs.update({'class':'form-control'})
使用
1.modelform对象生成标签:
先实例化 -- 将实例化对象传入html -- html页面循环该对象来生成标签
2.modelform对象保存数据
传入request.POST实例化 -- is_valid校验 -- 校验通过,对象.save()直接保存
3.modelform对象编辑数据
呈现原有数据:
把原来的数据先找到 -- .first()转为model对象 -- 实例化(instance=model对象) -- 再将实例化对象传给html页面 -- html页面循环该对象来生成标签
修改原有数据:
实例化(request.POST,instance=model对象) -- is_valid校验 -- 校验通过,对象.save()直接修改