modelForm 组件

概念

  将数据库与form 组件结合用起来的中间插件

与 form 组件的区别

form组件的难处:  

  form 可以实现 对数据的验证以及 form 的表单标签的生成

  但是她做不到一点就是无法将数据库串联起来,无法做到数据的传回

    比如编辑页面的时候无法拿到当前正要被编辑的值

modelfom 组件在 form组件的基础上进行升级 :

  自动创建 form 类 (将model类 转换成 form类)

  在 from类手动创建的是时候就可以发现,form 的创建和 model 的数据库几乎完全一致

  而modelform 可以帮我们直接实现这个操作而不在需要手动创建

    直接和 model 对应上,对于 model 的增删改查会更加的简单便捷

 创建关联

 用form 组件的形式创建

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())

用modelform 组件的形式创建

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

数据传回

和 form 组件的对比

  如果不用ModelForm,对于要显示原来的数据,需要挨个取一遍值,

  如果ModelForm,只需要加一个 instance=obj(obj是要修改的数据库的一条数据的对象)就可以得到同样的效果

  对当前编辑的对象的数据的取回,在form 组件的时候是无法操作的

    form 类在实例化对象的时候无法接受参数

    modelform 组件可以 以instance参数接受一个对象  

save 的使用

  对于数据的编辑更新和新建,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())

ModelForm的验证

用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={...})

# 你看不见我,

其实我有偷偷藏起来一份更加详细的博客 就在这里了。。。读书人的事情

Django_modelform组件的更多相关文章

  1. Python 目录指引

    1.0 Python 基础整合 1.1 变量 1.2 数据类型 1.3 基础语法 1.4 文件操作 1.5 函数 1.6 生成器 1.7 迭代器 1.8 装饰器 1.9 字符集 2.0 Python ...

  2. ExtJS 4.2 评分组件

    上一文章是扩展ExtJS自带的Date组件.在这里将创建一个评分组件. 目录 1. 介绍 2. 示例 3. 资源下载 1. 介绍 代码参考的是 Sencha Touch 2上的一个RatingStar ...

  3. react组件的生命周期

    写在前面: 阅读了多遍文章之后,自己总结了一个.一遍加强记忆,和日后回顾. 一.实例化(初始化) var Button = React.createClass({ getInitialState: f ...

  4. react-router 组件式配置与对象式配置小区别

    1. react-router 对象式配置 和 组件式配置    组件式配置(Redirect) ----对应---- 对象式配置(onEnter钩子) IndexRedirect -----对应-- ...

  5. Angular2入门系列教程3-多个组件,主从关系

    上一篇 Angular2项目初体验-编写自己的第一个组件 好了,前面简单介绍了Angular2的基本开发,并且写了一个非常简单的组件,这篇文章我们将要学会编写多个组件并且有主从关系 现在,假设我们要做 ...

  6. Angular2入门系列教程2-项目初体验-编写自己的第一个组件

    上一篇 使用Angular-cli搭建Angular2开发环境 Angular2采用组件的编写模式,或者说,Angular2必须使用组件编写,没有组件,你甚至不能将Angular2项目启动起来 紧接着 ...

  7. .NET Core 首例 Office 开源跨平台组件(NPOI Core)

    前言 最近项目中,需要使用到 Excel 导出,找了一圈发现没有适用于 .NET Core的,不依赖Office和操作系统限制的 Office 组件,于是萌生了把 NPOI 适配并移植到 .NET C ...

  8. .NetCore中的日志(1)日志组件解析

    .NetCore中的日志(1)日志组件解析 0x00 问题的产生 日志记录功能在开发中很常用,可以记录程序运行的细节,也可以记录用户的行为.在之前开发时我一般都是用自己写的小工具来记录日志,输出目标包 ...

  9. BootStrap_02之全局样式及组件

    1.BootStrap指定的四种屏幕尺寸: ①超大PC屏幕--lg(large):w>=1200px: ②中等PC屏幕--md(medium):1200px>w>=992px: ③P ...

随机推荐

  1. Fragment已经被added了导致的异常。

    java.lang.IllegalStateException: Fragment already added:  ******Effect 出现的原因是commit方法提交是异步的,所以容易出现,判 ...

  2. Several ports (8005, 8080, 8009) required by Tomcat v9.0 Server at localhost

    Several ports (8005, 8080, 8009) required by Tomcat v9.0 Server at localhost 问题:Tomcat服务器的端口被占用 解决: ...

  3. Django2.0 正则表示匹配的简单例子

    在Django中,使用正则表达式,匹配Url 默认情况下,url固定格式如下: urlpatterns = [ path('admin/', admin.site.urls), ] 如果需要使用正则表 ...

  4. Windows Server 2012 NIC Teaming 网卡绑定介绍及注意事项

    Windows Server 2012 NIC Teaming 网卡绑定介绍及注意事项 转载自:http://www.it165.net/os/html/201303/4799.html Window ...

  5. sqlserver中批量导出所有作业或链接脚本

    问题描述: 经常在数据库迁移到另外一台服务器的时候,需要把作业也迁移过去,但是作业有时候好多个,要是一个个编写监本出来很麻烦 今天知道个简单方法批量可以导出sql脚本,顺便做个笔记 解决方法: 1.在 ...

  6. bootstrap,bootstrap-table,bootstrapValidator,animate,layer配合起来搞事情

    资源准备(just download) bootstrap: http://www.bootcss.com/ bootstrap-table: http://bootstrap-table.wenzh ...

  7. Boosting Static Representation Robustness for Binary Clone Search against Code Obfuscation and Compiler Optimization(二)

    接着上篇Asm2Vec神经网络模型流程继续,接下来探讨具体过程和细节. 一.为汇编函数建模  二.训练,评估   先来看第一部分为汇编函数建模,这个过程是将存储库中的每一个汇编函数建模为多个序列.由于 ...

  8. php $$可变变量理解

    //在变量前面加上两个$$,如$$name,这表示可变变量,可以动态的设置和使用,先设置一个普通变量,一个可变变量会获取了一个普通变量的值作为这个可变变量的变量名 $a = 'b'; $b = 'c' ...

  9. linux ssh免密登陆远程服务器

    10.170.1.18服务器免密登录到10.170.1.16服务器 首先登入一台linux服务器(10.170.1.18),此台做为母机(即登入其他linux系统用这台做为入口):执行一行命令生成ke ...

  10. Nginx解读内置非默认模块 ngx_http_stub_status_module

    1 Background http://nginx.org/en/docs/http/ngx_http_stub_status_module.html ngx_http_stub_status_mod ...