ModelForm
内容回顾:
Model
- 数据库操作
- 验证
class A(MOdel):
user =
email =
pwd =
Form
class LoginForm(Form):
email = fields.EmailField()
user =
pwd =
- is_valid -> 每一个字段进行正则(字段内置正则) + clean_字段 -> clean(__all__) -> _post_clean
- cleand_data
- error
--------> 推荐 <--------- 1、Model操作 创建数据表
操作数据库表
数据验证(弱)
2、Form操作 数据验证(强大)
3、ModelForm 数据库操作
数据验证
适合小程序,特别方便
自定制
缺点:ModelForm的耦合性非常强,数据库操作和验证操作代码都放到一块,项目大了的话,代码无法分离;建议以后写程序Model和Form分开写
内容回顾
1、ModelForm简单验证
其他文件:
from django.db import models # Create your models here. class UserInfo(models.Model):
# verbose_name 等同于Form类里面的label
username = models.CharField(verbose_name='用户',max_length=32)
email = models.EmailField(verbose_name='邮件')
user_type = models.ForeignKey(verbose_name='类型',to='UserType',to_field='id') class UserType(models.Model):
caption = models.CharField(max_length=32) def __str__(self): #打印名称,不写显示的是obj对象
return self.caption
models.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/index/" method="post">
{% csrf_token %}
{{ obj.as_p }}
<input type="submit" value="提交"/>
</form> </body>
</html>
index.html
ModelForm文件:
from django import forms
from django.forms import fields
from app import models class UserInfoModelForm(forms.ModelForm):
class Meta:
model = models.UserInfo #去UserInfo类中获取数据
fields = '__all__' #__all__ 代指所有字段
# fields = ['username','email'] #指定显示的字段
# exclude = ['username'] #不显示的字段
处理文件:
from django.shortcuts import render
def index(request):
if request.method == 'GET':
obj = UserInfoModelForm()
return render(request,'index.html',{'obj':obj})
elif request.method == 'POST':
obj = UserInfoModelForm(request.POST)
result = obj.is_valid()
if result:
print(obj.cleaned_data) #如果models里没有__str__方法,则user_type获取
#到的是一个对象,可直接根据对象进行操作
print(obj.cleaned_data['user_type'])
# {'username': 'James', 'user_type': < UserType: 超级用户 >, 'email': 'ffd@fdsf.com'}
# 超级用户
else:
print(obj.errors)
return render(request,'index.html',{'obj':obj})
注:ModelForm最终继承了BaseForm,BaseForm里面具有is_valid方法,所以ModelForm也可以用is_valid进行验证
2、ModelForm组件
ModelForm
a. class Meta:
model, # 对应Model的
fields=None, # 字段
exclude=None, # 排除字段
labels=None, # 提示信息 labels ={'username':'用户名'}可写多个
help_texts=None, # 帮助提示信息 help_texts = {'username':'help info'}
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={...})
ModelForm所有组件
① 自定义插件widgets:
from django.forms import widgets as Fwidgets #避免跟widgets重名
class UserInfoModelForm(forms.ModelForm):
class Meta:
model = models.UserInfo #去UserInfo类中获取数据
fields = '__all__' #__all__ 代指所有字段
labels ={'username':'用户名'}
help_texts = {'username':'...'}
widgets = {
'username':Fwidgets.Textarea(attrs={'class':'c1'})
}
② 错误信息error_messages:
from django.forms import widgets as Fwidgets #避免跟widgets重名
class UserInfoModelForm(forms.ModelForm):
class Meta:
---snip---
error_messages = {
'__all__':{}, #整体的错误信息
'email':{'required':'邮箱不能为空'}
}
③ 自定义更改字段验证规则field_classes:
from django.forms import fields as Ffields #避免跟fields重名
class UserInfoModelForm(forms.ModelForm):
class Meta:
---snip---
field_classes ={
'email':Ffields.URLField #把邮件格式改为url格式验证
}
3、 ModelForm创建数据
其他文件:
from django.db import models # Create your models here. class UserInfo(models.Model):
# verbose_name 等同于Form类里面的label
username = models.CharField(verbose_name='用户',max_length=32)
email = models.EmailField(verbose_name='邮件')
user_type = models.ForeignKey(verbose_name='类型',to='UserType',to_field='id')
user_group = models.ManyToManyField('UserGroup') class UserType(models.Model):
caption = models.CharField(max_length=32) def __str__(self): #打印名称,不写显示的是obj对象
return self.caption class UserGroup(models.Model):
groupname = models.CharField(max_length=32) def __str__(self): #打印名称,不写显示的是obj对象
return self.groupname
models.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/index/" method="post">
{% csrf_token %}
{{ obj.as_p }}
<input type="submit" value="提交"/>
</form> </body>
</html>
index.html
from django import forms
from app import models
from django.forms import widgets as Fwidgets #避免跟widgets重名
from django.forms import fields as Ffields #避免跟fields重名
class UserInfoModelForm(forms.ModelForm):
class Meta:
model = models.UserInfo #去UserInfo类中获取数据
fields = '__all__' #__all__ 代指所有字段
labels ={'username':'用户名'}
help_texts = {'username':'...'}
widgets = {
'username':Fwidgets.Textarea(attrs={'class':'c1'})
}
error_messages = {
'__all__':{}, #整体的错误信息
'email':{'required':'邮箱不能为空'}
}
ModelForm验证
处理文件:
from django.shortcuts import render
def index(request):
if request.method == 'GET':
obj = UserInfoModelForm()
return render(request,'index.html',{'obj':obj})
elif request.method == 'POST':
obj = UserInfoModelForm(request.POST)
if obj.is_valid():
# 验证成功直接保存
obj.save() #默认commit=True,会保存多对多
# 保存一对多表单
# instance = obj.save(commit=False)
# instance.save()
# 保存多对多数据
# obj.save_m2m()
return render(request,'index.html',{'obj':obj})
4、ModelForm更新和初始化
描述:打开用户列表,显示用户信息,点击编辑跳转到编辑页面,Input显示选择用户的当前值;提交后,对数据进行更新
其他文件:
from django.conf.urls import url
from django.contrib import admin
from app import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/$', views.index),
url(r'^list/$', views.user_list),
url(r'^edit-(\d+)', views.user_edit),
]
urls.py
from django.db import models # Create your models here. class UserInfo(models.Model):
# verbose_name 等同于Form类里面的label
username = models.CharField(verbose_name='用户',max_length=32)
email = models.EmailField(verbose_name='邮件')
user_type = models.ForeignKey(verbose_name='类型',to='UserType',to_field='id')
user_group = models.ManyToManyField('UserGroup') class UserType(models.Model):
caption = models.CharField(max_length=32) def __str__(self): #打印名称,不写显示的是obj对象
return self.caption class UserGroup(models.Model):
groupname = models.CharField(max_length=32) def __str__(self): #打印名称,不写显示的是obj对象
return self.groupname
models.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
{% for row in list %}
<p>{{ row.username }}--{{ row.user_type.caption }}--<a href="/edit-{{ row.id }}">编辑</a></p>
{% endfor %}
</ul>
</body>
</html>
user_list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/edit-{{ nid }}" method="post">
{% csrf_token %}
{{ obj.as_p }}
<input type="submit" value="提交" />
</form> </body>
</html>
user_edit.html
处理文件:
from django.shortcuts import render
from django import forms
from app import models class UserInfoModelForm(forms.ModelForm):
class Meta:
model = models.UserInfo #去UserInfo类中获取数据
fields = '__all__' #__all__ 代指所有字段
labels ={'username':'用户名'}
help_texts = {'username':'...'} def user_list(request):
if request.method == 'GET':
list = models.UserInfo.objects.all().select_related('user_type')
return render(request,'user_list.html',{'list':list}) def user_edit(request,nid):
if request.method == 'GET':
user_obj = models.UserInfo.objects.filter(id=nid).first()
obj = UserInfoModelForm(instance=user_obj) # instance显示user_obj的对应值
return render(request, 'user_eidt.html', {'obj': obj,'nid':nid})
elif request.method == 'POST':
user_obj = models.UserInfo.objects.filter(id=nid).first()
obj = UserInfoModelForm(request.POST,instance=user_obj) #instance更新user_obj而不是添加
if obj.is_valid():
# 验证成功直接更新
obj.save()
else:
print(obj.errors.as_json())
return render(request, 'user_eidt.html', {'obj': obj,'nid':nid})
5、ModelForm钩子
ModelForm继承了is_valid方法,所以跟Form里的钩子用法一毛一样
class UserInfoModelForm(forms.ModelForm): class Meta:
---snip---
def clean_username(self):
pass
生成额外的标签:
class UserInfoModelForm(forms.ModelForm):
# 生成额外的标签 选择框
is_rmb = fields.CharField(widget=Fwidgets.CheckboxInput())
class Meta:
---snip---
《第二十四章》