ModelForm
1.Model与Form内容回顾
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
2.ModelForm的作用
Django中内置了Form和Model两个类,有时候页面的表单form类与Model类是一一对应,因此分别定义Form类和Model类会比较麻烦,最简单的方式就是通过Model来生成一个Form类,Django内置的ModelForm就是为此而生的.
ModelForm作为model和form的结合体,所以有以下功能:
- 验证
- 数据库操作
3.创建models.py
from django.db import models class UserType(models.Model): caption = models.CharField(max_length=32) class UserGroup(models.Model): name = models.CharField(max_length=32) class UserInfo(models.Model): username = models.CharField(verbose_name='用户',max_length=32) email = models.EmailField(verbose_name='邮箱') user_type = models.ForeignKey(to='UserType',to_field='id') u2g = models.ManyToManyField(UserGroup)
4.创建ModelForm,获取models.py字段数据
from django.shortcuts import render,HttpResponse,redirect from django import forms from app01 import models class UserInfoModelForm(forms.ModelForm): #ModelForm直接用models字段 class Meta: model = models.UserInfo #表示去models.py文件中UserInfo类获取字段 fields = '__all__' #获取所有字段 # fields = ['username','email','user_type'] #获取指定的字段 # exclude = ['username'] #获取username以外其他字段 def index(request): if request.method == "GET": obj = UserInfoModelForm() return render(request,"index.html",{'obj':obj}) elif request.method == "POST": obj = UserInfoModelForm(request.POST) print(obj.is_valid()) # 这是方法,别忘记了加括号 print(obj.cleaned_data) print(obj.errors) return render(request,"index.html",{'obj':obj})
5、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={...})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={...})
注意:导入模块名(fields、widgets)和字段名重复,所以导入时要起个别名。
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
关于Meta的使用方法:
class Meta:
model = models.UserInfo
fields = '__all__'
# fields = ['username','email']
# exclude = ['username']
labels = {
'username': '用户名',
'email': '邮箱',
'user_type':'一对多',
'u2g': '多对多',
}
help_texts = {
'username': '...'
}
widgets = {
'username': Fwidgets.Textarea(attrs={'class': 'c1'})
}
error_messages = {
'__all__':{ # 整体错误信息
},
'email': {
'required': '邮箱不能为空',
'invalid': '邮箱格式错误..',
}
}
field_classes = { # 定义字段的类是什么
# 'email': Ffields.URLField # 这里只能填类,加上括号就是对象了。
}
# localized_fields=('ctime',) # 哪些字段做本地化
6.ModelForm 数据库操作——创建数据save
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() # 等价以下三句 # instance = obj.save(False) # instance.save() # obj.save_m2m() return render(request,'index.html',{'obj': obj})
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/', views.index), ]
<!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>
7.ModelForm 数据库操作——修改数据
urlpatterns = [ url(r'^user_list/', views.user_list), #新增 url(r'^edit-(d+)/', views.user_edit), #新增 ]
def user_list(request): li = models.UserInfo.objects.all().select_related('user_type')#跨表取数据 return render(request,'user_list.html',{'li':li}) def user_edit(request,nid): #获取当前ID对象的用户信息 #显示用户已经存在数据 if request.method == 'GET': user_obj = models.UserInfo.objects.filter(id=nid).first() mf = UserInfoModelForm(instance=user_obj) #instance=user_obj,把默认数据传递进去,显示经存在数据 return render(request, 'user_edit.html',{'mf':mf,nid:'nid'}) elif request.method == 'POST': user_obj = models.UserInfo.objects.filter(id=nid).first() mf = UserInfoModelForm(request.POST,instance=user_obj) # 指定给谁做修改 if mf.is_valid(): mf.save() else: print(mf.errors.as_json) return render(request, 'user_edit.html',{'mf':mf,nid:'nid'})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> {% for k in li %} <li>{{ k.username }}-{{ k.user_type.caption }}-|<a href="/edit-{{ k.id }}">编辑</a></li> {% endfor %} </ul> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/edit-{{ nid }}/" method="post"> {% csrf_token %} {{ mf.as_p }} <input type="submit" value="提交"/> </form> </body> </html>