10.Django ModelForm
ModelForm
1.ModeForm简单验证
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
views.py
from django.shortcuts import render,redirect from app01 import models from django import forms from django.forms import fields class UserInfoModelForm(forms.ModelForm): class Meta: model = models.UserInfo # 去UserInfo类中获取数据 fields = '__all__' # __all__ 代指所有字段 # fields = ['username','email'] #指定显示的字段 # exclude = ['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) 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所有组件
(1)自定义插件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'}) }
(2)错误信息error_message
from django.forms import widgets as Fwidgets #避免跟widgets重名 class UserInfoModelForm(forms.ModelForm): class Meta: ---snip--- error_messages = { '__all__':{}, #整体的错误信息 'email':{'required':'邮箱不能为空'} }
(3)自定义更改字段验证规则field_classses
from django.forms import fields as Ffields #避免跟fields重名 class UserInfoModelForm(forms.ModelForm): class Meta: ---snip--- field_classes ={ 'email':Ffields.URLField #把邮件格式改为url格式验证 }
from django.shortcuts import render,redirect from app01 import models from django import forms from django.forms import fields from django.forms import widgets as Fwidgets from django.forms import fields as Ffields 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': '邮箱不能为空'} } field_classes = { 'email': Ffields.URLField # 把邮件格式改为url格式验证 } 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})
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
<!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>
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 app01 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), ]
from django.db import models 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
user_list.html
<!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_edit.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>
views.py
from django.shortcuts import render,redirect from app01 import models from django import forms from django.forms import fields from django.forms import widgets as Fwidgets from django.forms import fields as Ffields 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': '邮箱不能为空'} } 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}) 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_edit.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_edit.html', {'obj': obj, 'nid': nid})
皮豆设计(logo设计神器):http://pidou.cn