Form和ModelForm
Posted mengdie1978
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Form和ModelForm相关的知识,希望对你有一定的参考价值。
Form和ModelForm
- 进行数据校验,先看数据校验的过程
注册页面图解:
前端为了用户体验会做一些校验,不满足校验要求会报错
服务端也会对数据进行一些校验,不满足校验要求会报错
数据库也会对数据进行一些校验,不满足校验要求会报错
form组件和modleform组件就是让我们的数据校验过程更加简单一些,功能非常强大
Forms组件
- 提供了三个功能
1.能够帮我们生成HTML标签
2.标签中保留之前用户输入的数据
3.数据校验
forms组件的使用流程
- 1.在views.py文件中创建一个自定义的form类
from django import forms #需要先导入这个forms
class RegisterForm(forms.Form):
phone = forms.CharField()
username = forms.CharField()
password = forms.CharFied()
#用label参数可以将HTML中的label标签中内容显示为中文
phone = forms.CharField(label=\'手机号\')
username = forms.CharField(label=\'用户名\')
password = forms.CharField(label=\'密码\')
- 2.在views.py文件中写上视图函数
def register(request):
if request.method == \'GET\':
form = RegisterForm() #将上面的form类进行实例化
return render(request,\'register.html\',\'form\':form)#将实例化后的对象返回到html中生成对应的属性的标签
- 3.创建一个html文件,比如叫作register.html,内容如下
<!DOCTYPE html>
<html lang=\'en\'>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>注册页面</h1>
<form action=\'/register/\' method=\'post\' novalidate> #novalidate取消浏览器自带的错误提示
% csrf_token %
<div>
<!-- form.phone.id_for_label 相当于绑定下面生成的input标签中的id属性 -->
<!-- form.phone.label 相当于把后台自定义的中文渲染到标签中 -->
<label for=" form.phone.id_for_label "> form.phone.label </label>
<!-- form.phone相当于生成这个input标签<input type="text" name="phone" required="" id="id_phone"> -->
form.phone
</div>
<div>
<label for=" form.username.id_for_label "> form.username.label </label>
form.username
</div>
<div>
<label for=" form.password.id_for_label "> form.password.label </label>
form.password
</div>
<input type=\'submit\'>
</form>
</body>
</html>
保留原数据和校验功能
- forms组件代码
class RegisterForm(forms.Form):
#每个字段,默认都有一个required=True的参数,表示该字段数据不能为空
#phone = form.CharField(label=\'手机号\',required=True)
phone = forms.CharField(
label=\'手机号\',
required=True,
#错误提示信息的自定制
error_messages=
\'required\':\'小敏敏提示您,不能为空!\',
)
username = forms.CharField(label=\'用户名\')
password = forms.CharField(label=\'密码\')
- views.py内容如下
def register(request):
if request.method == \'GET\':
form = RegisterForm()
return render(request,\'register.html\',\'form\':form)
else:
print(request.POST)
form = RegisterForm(data=request.POST)
#把数据交给了RegisterForm,那么在通过form来渲染标签时,就将原来的的数据以默认值的形式(value=\'值\')生成在了对应标签上
if form.is_valid(): #执行校验,如果所有数据都校验通过了,返回True,但凡有一个数据没有通过校验,返回False
print(\'通过校验的数据\',form.cleaned_data)
return HttpResponse(\'ok\')
print(\'错误信息>>>\',form.errors)
return render(request,\'register.html\',\'form\':form)
- register.html内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
<!-- 给错误信息定制一些css样式 -->
.error_msg
font-size:12px;
color:red;
</style>
</head>
<body>
<h1>注册页面</h1>
<!-- form标签的这个novalidate属性,就是把浏览器自带的必填提示信息去掉 -->
<form action=\'/register/\' method=\'post\' novalidate>
% csrf_token %
<!-- form.errors 表示存放着所有字段的错误信息 -->
<div>
<label for=\' form.phone.id_for_label \'> form.phone.label </label>
form.phone
<!-- form.phone.errors.0 表示展示一个错误信息 -->
<span class=\'error_msg\'> form.phone.errors.0 </span>
</div>
<div>
<label for=\' form.username.id_for_label \'> form.username.label </label>
form.username
<span class="error_msg"> form.username.errors.0 </span>
</div>
<div>
<label for=\' form.password.id_for_label \'> form.password.label </label>
form.password
<span class=\'error_msg\'> form.password.errors.0 </span>
</div>
<input type=\'submit\'>
</body>
</html>
Form常用字段属性与插件
- initial 初始值
#生成input标签有个默认值
username = fomrs.CharField(label=\'用户名\',initial=\'小红\')
- widget 插件的意思,能够定制我们的标签显示效果
示例1 密文输入框
password = forms.CharField(
label=\'密码\',
#CharField默认插件是TextInput相当于type=\'text\',下面相当于修改type=\'password\',完整写法forms.widgets.PasswordInput,下面是简写
widget = forms.PasswordInput,
)
示例2 给标签加上一些其他属性
password = forms.CharField(
label=\'密码\',
#attrs=\'标签属性\':\'属性值\'
widget=forms.PasswordInput(attrs=\'class\':\'c1 c2\',\'placeholder\':\'请输入密码\'),
)
- 生成单选下拉框 ChoiceField默认插件是widget=forms.Select
#sex=forms.fields.ChoiceField() fields可以不用写
sex = forms.ChoiceField(
choices=((1,\'女\'),(2,\'男\')),
#(1,\'女\')生成一个option标签,value值为1,文本内容为女
label=\'性别\',
initial =2,#初始值
)
- 单选radio框 widget=forms.RadioSelect
sex = forms.ChoiceField(
choices=((1,\'女\'),(2,\'男\')),
label=\'性别\',
#initial =2,
#widget=forms.Select, #ChoiceField的默认插件
#input,type=\'radio\'的单选框
#widget=forms.RadioSelect,
#修改插件,并设置属性
widget=forms.RadioSelect(attrs=\'class\':\'c1\')
)
- 多选下拉框 MultipleChoiceField
hobby = forms.MultipleChoiceField(
choices=((1,\'喝酒\'),(2,\'抽烟\'),(3,\'励志\')),
label=\'爱好\'
)
- 多选checkbox框 widget=forms.CheckboxSelectMultiple
hobby = forms.MultipleChoiceField(
choices=((1,\'喝酒\'),(2,\'抽烟\'),(3,\'励志\')),
label = \'爱好\',
#widget=forms.CheckboxInput, #做单选功能的复(多)选框形式,必须勾选协议的那个选框
widget=forms.CheckboxSelectMultiple,
)
- 单选功能的复选框形式,像那种勾选同意协议的那个选框 widget=forms.CheckboxInput 里面choices只有true或false
status = forms.MultipleChoiceField(
choices=((\'True\',同意),(\'Flase\',不同意))
label=\'同意是否勾选协议\',
widget=forms.CheckboxInput,
)
- date类型
bday = forms.CharField(
label=\'生日\',
widget=forms.TextInput(attrs=\'type\':\'date\'), 只要设置一个date属性就可以了
)
单选或多选框使用数据库中的数据
- 方式1 forms.ModelChoiceField
models中的模型类
class Publish(models.Model):
name = models.CharField(max_length=32)
def __str__(self):
return self.name
form类中的字段写法
#生成选择框,并使用数据库中的数据 必须要用这个ModelChoiceField
publish = forms.ModelChoiceField(
queryset=models.Publish.objects.all(), #必须是queryset
)
会自动生成单选下拉框,并且option标签value属性对应的值,是queryset参数对应的queryset集合里面的models模型类对象的id值,option标签的文本内容是每个models模型类对象。
#生成标签的时候,页面显示第一层会有个自带的\'--------\',第二个往后才是数据
- 方式2 forms.ChoiceField
publish = forms.ChoiceField(
choices=models.Publish.objects.all().values_list(\'id\',\'name\')
#quertset[(1,\'xx出版社\'),]
)
#生成标签的时候,没有上面那个自带的\'--------\',直接就显示的是数据
Django(Form,ModelForm)
FORM表单:
Django表单系统中,所有的表单类都作为django.forms.Form的子类创建,包括ModelForm
关于django的表单系统,主要分两种
基于django.forms.Form:所有表单类的父类
基于django.forms.ModelForm:可以和模型类绑定的Form
需求:向数据库的Info表中添加一些新的个人信息
FORM的用法
from django import forms from app01 import models from django.core.exceptions import ValidationError class Info_form(forms.Form): def validate_name(value): try: models.Info.objects.get(name=value) raise ValidationError(‘%s 的信息已经存在!‘%value) except models.Info.DoesNotExist: pass sex_choice=((0,‘男‘), (1,‘女‘))#select的数据可以像这样写,也可以在另外一张表中动态去拿 name = forms.CharField(validators=[validate_name],label=‘姓名‘,error_messages={‘required‘:‘必填‘}) age = forms.CharField(label=‘年龄‘,error_messages={‘required‘:‘必填‘}) # sex = forms.CharField(label=‘性别‘,error_messages={‘required‘:‘必填‘,},) sex=forms.IntegerField(widget=forms.widgets.Select(choices=sex_choice, attrs={‘class‘:‘setform2‘} )) birthday = forms.CharField(label=‘生日‘,error_messages={‘required‘:‘必填‘}) qualification = forms.CharField(label=‘学历‘,error_messages={‘required‘:‘必填‘}, widget=forms.TextInput(attrs={‘class‘:‘formset‘, ‘placeholder‘:‘本科‘ } )) email=forms.EmailField(max_length=100,min_length=10) job = forms.CharField(label=‘工作‘,error_messages={‘required‘:‘必填‘}) def __init__(self,*args,**kwargs): super(Info_form,self).__init__(*args,**kwargs) self.fields[‘hobby‘]=forms.CharField(widget=forms.widgets.Select(choices=models.Hobby.objects.values_list(‘id‘,‘item‘))) #-------------------------------------------------------views.py #------------------------------------------------------- from django.shortcuts import render,HttpResponse # Create your views here. from app01.models import * from app01.forms import * def add_info(req): if req.method==‘POST‘: Info_form_obj=Info_form(req.POST) if Info_form_obj.is_valid(): Info.objects.create(name=Info_form_obj.cleaned_data[‘name‘], age=Info_form_obj.cleaned_data[‘age‘], sex=Info_form_obj.cleaned_data[‘sex‘], birthday=Info_form_obj.cleaned_data[‘birthday‘], qualification=Info_form_obj.cleaned_data[‘qualification‘], job=Info_form_obj.cleaned_data[‘job‘] ) return HttpResponse(‘添加成功!‘) else: error_obj=Info_form_obj.errors print(‘***************‘) print(type(error_obj))#<class ‘django.forms.utils.ErrorDict‘> print(error_obj[‘name‘][0])#必填 print(error_obj.get(‘age‘))#<ul class="errorlist"><li>必填</li></ul> return render(req,‘add_info.html‘,{‘form_obj‘:Info_form_obj,‘error_obj‘:error_obj}) Info_form_obj=Info_form() return render(req,‘add_info.html‘,{‘form_obj‘:Info_form_obj}) #------------------------------------------------------add_info.html #------------------------------------------------------- <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>添加个人信息</title> <style> .formset{ color: rebeccapurple; border: dashed cadetblue; } </style> </head> <body> <form action="{% url ‘add_info‘ %}" method="post"> <p>姓名{{ form_obj.name }}{{ error_obj.name.0 }}</p> <p>年龄{{ form_obj.age }}{{ error_obj.age.0 }}</p> <p>生日{{ form_obj.birthday }}{{ error_obj.birthday.0 }}</p> <p>工作{{ form_obj.job }}<span>{{ error_obj.job }}</span></p> <p>学历{{ form_obj.qualification }}<span>{{ error_obj.qualification }}</span></p> <p>性别{{ form_obj.sex }}<span>{{ error_obj.sex }}</span></p> <p>邮箱{{ form_obj.email }}<span>{{ error_obj.email }}</span></p> <p>爱好{{ form_obj.hobby }}<span>{{ error_obj.hobby }}</span></p> {# {{ form_obj.as_p }}#} <input type="submit" value="提交"><br> {% csrf_token %} </form> </body> </html>
MODELFORM基本操作:
ModelForm
a.
class
Meta:
model,
# 对应Model的
fields
=
None
,
# 字段
exclude
=
None
,
# 排除字段
labels
=
None
,
# 提示信息
help_texts
=
None
,
# 帮助提示信息
widgets
=
None
,
# 自定义插件
error_messages
=
None
,
# 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS)
field_classes
=
None
# 自定义字段类 (也可以自定义字段)
localized_fields
=
(
‘birth_date‘
,)
# 本地化,如:根据不同时区显示数据
如:
数据库中
2016
-
12
-
27
04
:
10
:
57
setting中的配置
TIME_ZONE
=
‘Asia/Shanghai‘
USE_TZ
=
True
则显示:
2016
-
12
-
27
12
:
10
:
57
b. 验证执行过程
is_valid
-
> full_clean
-
> 钩子
-
> 整体错误
c. 字典字段验证
def
clean_字段名(
self
):
# 可以抛出异常
# from django.core.exceptions import ValidationError
return
"新值"
d. 用于验证
model_form_obj
=
XXOOModelForm()
model_form_obj.is_valid()
model_form_obj.errors.as_json()
model_form_obj.clean()
model_form_obj.cleaned_data
e. 用于创建
model_form_obj
=
XXOOModelForm(request.POST)
#### 页面显示,并提交 #####
# 默认保存多对多
obj
=
form.save(commit
=
True
)
# 不做任何操作,内部定义 save_m2m(用于保存多对多)
obj
=
form.save(commit
=
False
)
obj.save()
# 保存单表信息
obj.save_m2m()
# 保存关联多对多信息
f. 用于更新和初始化
obj
=
model.tb.objects.get(
id
=
1
)
model_form_obj
=
XXOOModelForm(request.POST,instance
=
obj)
...
PS: 单纯初始化
model_form_obj
=
XXOOModelForm(initial
=
{...})
以上是关于Form和ModelForm的主要内容,如果未能解决你的问题,请参考以下文章