Django之ModelForm组件
一 内容回顾
我们之前单独学习过Model(操作数据库)和Form(验证用户数据、生成HTML标签),简单回顾如下:
models.py(Model)
from django.db import models
class UserInfo(models.Model):
name = models.CharField(max_length=64)
email = models.EmailField()
pwd = models.CharField(max_length=64)
ug = models.ForeignKey('UserGroup',null=True,blank=True)
def __str__(self):
return self.name
class UserGroup(models.Model):
title = models.CharField(max_length=64)
def __str__(self):
return self.title
views.py(Form)
from django.shortcuts import render,HttpResponse,redirect
from django.forms import Form,fields,widgets,ModelForm
from app01 import models
class UserInfoForm(Form):
name = fields.CharField(label='用户名')
email = fields.EmailField(label='邮箱')
pwd = fields.CharField(label='密码')
ug_id = fields.ChoiceField(
label='部门',
widget=widgets.Select,
choices=[]
)
# 使数据在网页上实时更新
def __init__(self,*args,**kwargs):
super(UserInfoForm,self).__init__(*args,**kwargs)
self.fields['ug_id'].choices = models.UserGroup.objects.values_list('id','title')
def test(request):
if request.method == 'GET':
form = UserInfoForm()
else:
form = UserInfoForm(request.POST,request.FILES)
if form.is_valid():
models.UserInfo.objects.create(**form.cleaned_data)
return redirect('http://www.baidu.com')
content = {
'form': form
}
return render(request, 'test.html', content)
test.html(展示页面)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="POST" novalidate>
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="提交" />
</form>
</body>
</html>
二 ModelForm基本操作
ModelForm为Model和Form的结合体,所以它具备以下功能:
- 操作数据库
- 用户请求验证
- 生成HTML标签
2.1 通过ModelForm实现以上功能
from django.shortcuts import render,HttpResponse,redirect
from django.forms import Form,fields,widgets,ModelForm
from app01 import models
class UserInfoModelForm(ModelForm):
class Meta:
model = models.UserInfo # 与models建立了依赖关系
fields = "__all__"
def test(request):
if request.method == "GET":
form_obj = UserInfoModelForm()
else:
form_obj = UserInfoModelForm(request.POST,request.FILES)
if form_obj.is_valid():
form_obj.save() # 直接将数据添加到数据库中
return redirect('http://www.baidu.com')
content = {
'form_obj': form_obj
}
return render(request, 'test.html', content)
2.2 自定制字段名
如何定义http上定义的字段,自定义写成中文?之前的用法是在Form里写上label。ModelForm定义要用verbose_name
models.py
class UserInfo(models.Model):
name = models.CharField(max_length=64, verbose_name='用户名')
email = models.EmailField(verbose_name='邮箱')
pwd = models.CharField(max_length=32, verbose_name='密码')
ug = models.ForeignKey('UserGroup', null=True, blank=True,verbose_name='部门')
如果不在model里定义,在ModelForm里实现,利用labels
class UserInfoModelForm(ModelForm):
class Meta:
model = models.UserInfo # 与models建立了依赖关系
fields = "__all__"
labels = {
'name':'用户名',
'email':'邮箱',
'pwd':'密码',
'ug_id':'部门',
}
2.3 显示指定的列
fields = "__all__" # 显示所有字段 fields = ['username','email'] # 显示指定列 exclude = ['username'] # 不显示指定列
2.4 modelForm验证原理
# Form验证:
UserInfoForm -> Form -> BaseForm( 包含is_valid等方法)
# ModelForm验证:
UserInfoModelForm -> ModelForm -> BaseModelForm -> BaseForm
三 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)
model_form_obj = XXOOModelForm(instance=obj) # 当前model对象,用于查询或修改操作等
PS: 单纯初始化
model_form_obj = XXOOModelForm(initial={...})
注意:导入模块名(fields、widgets)和字段名重复,所以导入时要起个别名
from django.forms import Form,fields,widgets,ModelForm
from app01 import models
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
class UserInfoModelForm(ModelForm):
textarea = Ffields.CharField(widget=Fwidgets.Textarea()) # 自定义新字段或覆盖原有字段
# name = Ffields.CharField(widget=Fwidgets.Textarea())
class Meta:
model = models.UserInfo
fields = '__all__'
# fields = ['name','email']
# exclude = ['name']
labels = {
'name':'用户名',
'email':'邮箱',
'pwd':'密码',
'ug_id':'部门',
}
help_texts = {
'name': '请输入用户名'
}
widgets = {
'name': Fwidgets.Input(attrs={'class': 'c1'})
}
error_messages = {
'__all__':{ # 整体错误信息
},
'email': {
'required': '邮箱不能为空',
'invalid': '邮箱格式错误',
}
}
field_classes = { # 定义字段的类是什么
'email': Ffields.URLField # 这里只能填类,加上括号就是对象了
}
四 ModelForm 数据库操作
4.1 创建数据
如果数据验证是ok的,那么save,就直接在数据库中创建完数据了
if obj.is_valid():
obj.save() # 创建数据
如果存在多对多的关系,执行obj.save()会在当前表和多对多关系表里都增加数据。
save具体做了什么?
if obj.is_valid():
obj.save() # 等价以下三行代码
# instance = obj.save(False)
# instance.save() # 当前对象表数据创建
# obj.save_m2m() # 多对多表数据创建
# 上面三行代码完成的是和上面obj.save() 一样的操作,拆开可自定制操作
save源码:
def save(self, commit=True):
""""""
if commit:
self.instance.save() # 指的当前model对象
self._save_m2m() # 指:保存m2m对象
else:
self.save_m2m = self._save_m2m
return self.instance # model 类的对象
""""""
所以instance = obj.save(False)时,什么都没有操作
4.2 修改数据
修改表数据时,将instance信息传进去,不然是新建数据,而不是对某行数据进行修改。
user_obj = models.UserInfo.objects.filter(id=nid).first() # 获取指定对象
xx = UserInfoModelForm(request.POST,instance=user_obj) # 给指定对象做修改
if xx.is_valid():
xx.save()
五 ModelForm钩子、额外字段
数据验证钩子
从上面的Form和ModelForm中,他们都是继承了BaseForm,而is_valid()是在BaseForm中定义的,所以ModelForm也能和Form一样使用各种钩子
额外字段
像网页上的checkbox,一个月内免登陆,用提交到数据库么?这个只需要设置session和cookie就可以了
class UserInfoModelForm(ModelForm):
xxx = fields.CharField(widget=widgets.CheckboxInput()) # 额外字段,也可同名,即将之前的覆盖
class Meta:
model = models.UserInfo
fields = '__all__'
六 补充说明
# 生成HTML标签 class Meta: ... # 生成默认值 obj = xxxModelForm(instance=ModelObj)

浙公网安备 33010602011771号