ModelForm
顾名思义就是讲model和form结合起来啦。原来用form组件的时候。form和model分开,我们在使用form组件 的时候还要创建自己的字段,现在modelform直接可以用model里面的数据啦。
废话不说 直接看代码
from django.db import models # Create your models here. class Author(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) age = models.IntegerField() email=models.EmailField(max_length=32) # 与AuthorDetail建立一对一的关系 def __str__(self): return self.name class Publish(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) city = models.CharField(max_length=32) email = models.EmailField() def __str__(self): return self.name class Book(models.Model): nid = models.AutoField(primary_key=True) title = models.CharField(max_length=32) publishDate = models.DateTimeField() price = models.DecimalField(max_digits=5, decimal_places=2) # 与Publish建立一对多的关系,外键字段建立在多的一方 publish = models.ForeignKey(to="Publish", to_field="nid") # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表 authors = models.ManyToManyField(to='Author') def __str__(self): return self.title
from django.forms import ModelForm,widgets as wd,fields from app01 import models class BookModelForm(ModelForm): class Meta: model=models.Book fields="__all__" #如果不想用全部字段直接选取自己需要的字段即可 #files=["title","price,"authors"] error_messages={ 'title':{"required":"书名不能为空"}, 'price':{"invilid":"价格只能是数字"} } #一般不指定默认就有 widgets={ 'title':wd.TextInput(attrs=({"id":"title"})), 'price':wd.TextInput(attrs={"id":"price"}), 'publish':wd.Select(attrs={"id":"publish"}), } labels={ "title":"书名", 'publishDate':'出版日期', 'publish':'出版社', 'price':'价格', 'authors':'作者' } #当然还有钩子函数
from django.shortcuts import render,redirect,HttpResponse from app01 import models from app01.forms import BookModelForm # Create your views here. def index(request): books=models.Book.objects.all() return render(request,"index.html",{"books":books}) def addBook(request): if request.method=="POST": form=BookModelForm(request.POST) print(form) if form.is_valid(): form.save() return redirect("/index/") print(form.errors) return render(request,"addBook.html",{"form":form}) form =BookModelForm() return render(request,"addBook.html",{"form":form}) def editBook(request,id): book=models.Book.objects.filter(nid=id).first() if not book: return HttpResponse("eror") else: if request.method=="POST": form=BookModelForm(instance=book,data=request.POST) if form .is_valid(): form.save() return redirect("/index/") else: form=BookModelForm(instance=book) return render(request,"editBook.html",{"form":form,"id":id})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> </head> <body> <div class="table-responsive table-bordered"> <table id="t1" class="table table-striped table-bordered"> <thead> <tr> <th>编号</th> <th>书名</th> <th>出版日期</th> <th>价格</th> <th>出版社</th> <th>作者</th> <th>操作</th> </tr> </thead> <tbody> {% for book in books %} <tr> <td class="hide">{{ book.nid }}</td> <td>{{ forloop.counter }}</td> <td>{{ book.title }}</td> <td>{{ book.publishDate|date:"Y-m-d " }}</td> <td>{{ book.price }}</td> <td>{{ book.publish }}</td> <td > {% for author in book.authors.all %} {{ author.name }} {% endfor %} </td> <td> <a href="/editBook/{{ book.nid }}/"> <button class="btn btn-warning">编辑</button> </a> <a href="/delBook/{{ book.id }}/"> <button class="btn btn-danger del">删除</button> </a> </td> </tr> {% endfor %} </tbody> </table> </div> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <form action="/editBook/{{ id }}/" method="post"> {% csrf_token %} {{ form.as_p }} <p><input type="submit"></p> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <form action="/addBook/" method="post"> {% csrf_token %} <div>书名{{ form.title }}{{ form.errors.title.0 }}</div> <div>出版日期{{ form.publishDate }}{{ form.errors.publishDate.0 }}</div> <div>jiage{{ form.price }}{{ form.errors.price.0 }}</div> <div>出版设{{ form.publish }}</div> <div>作者{{ form.authors }}</div> <p><input type="submit"></p> </form> </body> </html>
注意:导入模块名(fields、widgets)和字段名重复,所以导入时要起个别名。具体见上面代码
modelform相关知识
自定制字段名
如何定义http上定义的字段呢,自定义写成中文的?之前的用法是在Form里写上label。Model Form定义要用verbose_name
models.py
class UserInfo(models.Model): username = models.CharField(max_length=32, verbose_name='用户') email = models.EmailField(verbose_name='邮箱') user_type = models.ForeignKey(to='UserType',to_field='id', verbose_name='类型')
如果不在model里定义,在modelForm里实现,利用labels
class UserInfoModelForm(forms.ModelForm): class Meta: model = models.UserInfo fields = "__all__" labels = { 'username':'用户名', 'email':'邮箱', }
展示指定的列
fields = "__all__"
上面展示所有的,可不可以展示指定的列
fields = ['username','email'] # 显示指定列 exclude = ['username'] # 排除指定列
为什么modelForm里也能做验证?
form里面有is_valid
,cleaned_data
,errors
,
# 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) ... PS: 单纯初始化 model_form_obj = XXOOModelForm(initial={...})
- Model Form 应用场景: - ModelForm - 中小型应用程序 - Form - 大型应用程序 * 注意事项: - 1. 类 class Foo(ModelForm): class Meta: # model = models.Role # fields = "__all__" # fields = ['caption',] # exclude = ['catpion'] model = models.UserType fields = "__all__" error_messages = { 'title':{'required':'名称不能为空','invalid':'格式错误'} } widgets = { 'title':wd.TextInput(attrs={'class':'c1'}) } - 2. 添加 GET: form = Foo() POST: form = Foo(data=request.POST) form.is_valid() form.cleaned_data form.erros form.save() - 3. 修改 GET: form = Foo(instance=obj) POST: form = Foo(instance=obj,dat=request.POST) ... form.save()