将数据库与form 组件结合用起来的中间插件html
form组件的难处: 前端
form 能够实现 对数据的验证以及 form 的表单标签的生成git
可是她作不到一点就是没法将数据库串联起来,没法作到数据的传回数据库
好比编辑页面的时候没法拿到当前正要被编辑的值django
modelfom 组件在 form组件的基础上进行升级 :json
自动建立 form 类 (将model类 转换成 form类)函数
在 from类手动建立的是时候就能够发现,form 的建立和 model 的数据库几乎彻底一致ui
而modelform 能够帮咱们直接实现这个操做而不在须要手动建立url
直接和 model 对应上,对于 model 的增删改查会更加的简单便捷 spa
class Book(models.Model): title=models.CharField(max_length=32) price=models.DecimalField(max_digits=8,decimal_places=2) # 999999.99 date=models.DateField() publish=models.ForeignKey("Publish") authors=models.ManyToManyField("Author") class BookForm(forms.Form): title = forms.CharField(max_length=32,label="书籍名称") price = forms.DecimalField(max_digits=8, decimal_places=2,label="价格") # 999999.99 date = forms.DateField( label="日期", widget=widgets.TextInput(attrs={"type":"date"}) ) publish=forms.ModelChoiceField(queryset=Publish.objects.all()) authors=forms.ModelMultipleChoiceField(queryset=Author.objects.all())
class BookForm(ModelForm): class Meta: model=Book # 制定要被转换的表 fields="__all__" # 控制要被转换的字段 , __all__ 表示全部字段 ,除了 用 __all__ 的时候对多个字段使用的时候用列表的形式 # fields=["title","price"] # 除了 用 __all__ 的时候用字符串形式,对多个字段使用的时候用列表的形式
常见仓鼠:
from django.forms import ModelForm #在视图函数中,定义一个类,好比就叫StudentList,这个类要继承ModelForm,在这个类中再写一个原类Meta(规定写法,并注意首字母是大写的) #在这个原类中,有如下属性(部分): class StudentList(ModelForm): class Meta: # 对应的Model中的类 model =Student # 注意这里千万别加 "," 会识别成元组致使报错 # 字段,若是是__all__,就是表示列出全部的字段 fields = "__all__" # fields = ["name","age"] # 指定显示某些字段 # 排除的字段 # exclude = ["name","age"] exclude = none# error_messages 错误信息
# 自定义错误信息(总体错误信息from django.core.exceptions import NON_FIELD_ERRORS) error_messages = { '__all__':{}, # 总体的错误信息放在这里 'name':{'required':"用户名不能为空",}, # 个别字段的错误信息单独显示 'age':{'required':"年龄不能为空",}, }
# widgets 用法,好比把输入用户名的input框给为Textarea# 首先得导入模块 from django.forms import widgets as wid #由于重名,因此起个别名 widgets = { # 这个widgets只是一个参数名,不要搞混 "name":wid.Textarea(attrs={"class":"c1"}) #还能够自定义属性 } # labels 自定义在前端显示的名字 labels= { "name":"用户名" } # help_texts 显示帮助信息 help_texts={ "name":"这里写你的名字" }
# field_classes 自定义字段类 field_classes={ 'email':fields.URLField #这里只能填类,不能加括号,加上括号就变成对象了。
# 这是把邮箱的默认邮箱类自定义成url类了。 }
ps:
在没有用 form 以及 modelform 以前, 这两个本质都是同样,都是保存的就是字符串而已,实际上是没有意义的
只有 form 以及 modelform 才能够对他们进行校验,在这时候 UUIDField , EmailField 之类的才有意义
由于只有 form 以及 modelform 才能够将 models.xxxx 转换成 forms.xxx 的时候进行本身的 is_vaild 方法进行相关的校验
name = models.CharField
name = models.UUIDField name = models.URLField name = models.EmailField name = models.IPAddressField
若是不用ModelForm,对于要显示原来的数据,须要挨个取一遍值,
若是ModelForm,只须要加一个 instance=obj(obj是要修改的数据库的一条数据的对象)就能够获得一样的效果
对当前编辑的对象的数据的取回,在form 组件的时候是没法操做的
form 类在实例化对象的时候没法接受参数
modelform 组件能够 以instance参数接受一个对象
对于数据的编辑更新和新建,modelform 类统一使用 .save() 方法
当 当前的 modelform 对象中没有 instance参数的时候默认添加一个新对象
当 当前的 modelform 对象中有 instance参数的时候会按照参数的中的对象进行更新操做
(不给对象参数的话怎么知道要编辑哪个呢?)
def addbook(request): if request.method == "POST": form = BookForm(request.POST) if form.is_valid(): form.save() # form.model.objects.create(request.POST)
return redirect("/books/") else: return render(request, "add.html", locals()) form=BookForm() return render(request, "add.html", locals()) def editbook(request, edit_book_id): # 被编辑的书的对象 edit_book = Book.objects.filter(pk=edit_book_id).first() if request.method == "POST": form = BookForm(request.POST, instance=edit_book) if form.is_valid(): form.save() # edit_book.update(request.POST)
return redirect("/books/") form=BookForm(instance=edit_book) return render(request, "edit.html",locals())
用form方法的时候,验证功能的函数实际上是写在BaseForm里的:UserInfoForm-->继承了Form--->继承了BaseForm(is_valid......)
点击提交的时候,modelform也能够作验证。UserInfoModelForm-->继承了ModelForm--->继承了BaseModelForm--->继承了BaseForm(is_valid......)
UserInfoModelForm下面也应该有obj.is_valid(), obj.cleaned_data, obj.errors 等方法。
ModelForm 作验证的时候与Form方法是同样的。
咱们能够像使用Form类同样自定义局部钩子方法和全局钩子方法来实现自定义的校验规则。
若是咱们不重写具体字段并设置validators属性的话,ModelForm是按照模型中字段的validators来校验的。
modelform 组件在 form 组件的基础上,保留了 form 组件的所有功能
并且 更加简单的实现了与model 表的映射建立
而且新增了与model 表的连接得以能够对当前操做的对象直接操做
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={...})
# 你看不见我,
其实我有偷偷藏起来一份更加详细的博客 就在这里了。。。读书人的事情