Model、Form、ModelForm

本节内容:

1:Model

2:Form

3:Model Form

1
2
3
http://www.cnblogs.com/wupeiqi/articles/6144178.html  武sir:Form组件
http://www.cnblogs.com/wupeiqi/articles/6216618.html  武sir:Model
http://www.cnblogs.com/wupeiqi/articles/6229414.html  武sir:ModelForm

Model ==> 强大的数据库操作,弱小的数据验证。

Form ==>强大的数据验证

ModelForm ===>二者结合,强大的数据验证,适中的数据库操作。在ModelForm是能够封装一个model对象。

1:Model

对于Model来说,他的验证是需要自己去创建一个model对象,然后去进行判断

model:
针对单一字段 :full_clean
针对多个的字段: clean full_clean -- >字段正则判定 -- >clean方法(钩子)
他是没有最终产物

views:

def fm(request):
obj = models.News(title='root')
##full_clean就进行了验证,如果要是有errors的话,就直接报错,所以在进行验证的时候,我们要自己做try判断
obj.full_clean() ##进行model的验证。里面的def clean 方法
obj.save() ##报错 django.core.exceptions.ValidationError: {'__all__': ['title不能是root']}
return render(request,"form.html",locals())

models:

from django.db import models
from django.core.exceptions import ValidationError class News(models.Model):
title = models.CharField(max_length=) ##验证错误会输出到errors中去
def clean(self):
if self.title == "root":
raise ValidationError("title不能是root")

model的源码分析:

 def full_clean(self, exclude=None, validate_unique=True):
"""
Call clean_fields(), clean(), and validate_unique() on the model.
Raise a ValidationError for any errors that occur.
"""
errors = {}
if exclude is None:
exclude = []
else:
exclude = list(exclude) try:
self.clean_fields(exclude=exclude) ####执行单个字段的验证
except ValidationError as e:
errors = e.update_error_dict(errors) # Form.clean() is run even if other validation fails, so do the
# same with Model.clean() for consistency.
try:
self.clean() ####执行clean的方法验证
except ValidationError as e:
errors = e.update_error_dict(errors) ###如果错误,把错误添加到errors中 # Run unique checks, but only for fields that passed validation.
if validate_unique:
for name in errors:
if name != NON_FIELD_ERRORS and name not in exclude:
exclude.append(name)
try:
self.validate_unique(exclude=exclude)
except ValidationError as e:
errors = e.update_error_dict(errors) if errors: ###如果有错误,就直接报错了,so 我们要自己去views视图中去判断,try
raise ValidationError(errors)

2:Form

有着强大的验证功能: 具体看源码。

对于Form来说,是当一个请求来了,直接进行post数据的验证,如果是错误会有一个obj.errors的错误对应。

Form :有强大的验证
针对单一字段的: full_clean
自定义针对单一字段的: clean_username
针对多个字段的: clean 【or】port_clean (这个是不能出现异常,只能添加异常) is_valid() -- >full_clean () -->
-->每个字段的正则,每个字段clean_字段名()
-->clean_form -->clean(钩子)
-->_post_clean(钩子) 验证后的产物:clean_date 或obj.errors

Form中要获取数据库的实时数据:

两种方式:

1
第二种方式,虽然是可以用但是它的可定制性差。是需要依赖model的

浏览器中:显示

3:ModelForm

Model、Form、ModelForm三者的结合:

在公司比较大的时候:比如说:
models文件是放在A项目中
forms是放在B项目中 froms是没办法导入models中的数据的。
我们就让Form单独的做数据验证,而model就单纯的做数据库操作各司其职是完美的。 但是dajngo还存在了一种叫ModelForm的东西,他是结合了model和Form的功能。

Form和ModelForm的继承关系:

Form:
继承关系:
UserForm -- > Form -- >BaseForm
ModelForm:
继承关系:
NewsModelForm -->ModelForm -->BaseModelForm -->BaseForm 所以modelForm和Form是有同一个祖宗的,Form中的BaseForm的功能,ModelForm也一样可以使用。

ModelForm的简单使用:

from django.db import models
from django.core.exceptions import ValidationError class User_Type(models.Model):
name = models.CharField(max_length=)
def __str__(self):
return self.name class Tags(models.Model):
name = models.CharField(max_length=)
def __str__(self):
return self.name class News(models.Model):
title = models.CharField(max_length=)
type = models.ForeignKey(User_Type,on_delete=models.CASCADE,blank=True,null=True)
tag = models.ManyToManyField(Tags) ##验证错误会输出到errors中去
def clean(self):
if self.title == "root":
raise ValidationError("title不能是root")

model

from django.forms import  Form  ##Form要继承的
from django.forms import ModelForm ##ModelForm继承
from web import models class NewsModelForm(ModelForm):
class Meta:
model = models.News ##里面必须要有一个model,因为他是对每个models类做增删改查的
fields = "__all__" ##指定了类,要需要指定要处理哪几个字段 __all__是全部字段 def mf(request):
if request.method == "GET":
obj = NewsModelForm()
if request.method == "POST":
obj = NewsModelForm(data=request.POST) ##传入进行验证
if obj.is_valid():
#models.News.objects.create(**obj.cleaned_data) ##以前Form的时候添加数据要这样写
obj.save() ##modelform现在可以直接save就可以,save的时候可以保存一对多、多对多的数据
else:
print(obj.errors)
return render(request, "mf.html", locals())

template: [是不需要执行上面的什么__init__方法、和第二种方法]直接就可以实时了。

<form action="" method="post">
{% csrf_token %}
{{ obj.as_p }}
<input type="submit">
</form>

ModelForm的另一个功能:修改

urls:

1
re_path('edit-(\d+).html',views.edit)

views:

class NewsModelForm(ModelForm):
class Meta:
model = models.News ##里面必须要有一个model,因为他是对每个models类做增删改查的
fields = "__all__" ##指定了类,要需要指定要处理哪几个字段 __all__是全部字段 def edit(request,nid):
if request.method == "GET":
model_obj = models.News.objects.get(id=nid) ##获取model对象
obj = NewsModelForm(instance=model_obj)
else:
model_obj = models.News.objects.get(id=nid)
obj = NewsModelForm(request.POST,instance=model_obj) ##修改的时候是需要instance 的!如果没有则默认就是增加数据的
if obj.is_valid():
# obj.save() ##他里面的源码默认是commit=True 会帮你第三张表一起修改了。而在django是可以自己手动指定修改的
mobj = obj.save(commit=False) #要是commit为False的话,他会返回一个model的对象、点击commit看源码
mobj.save() ##保存自己表中数据
mobj.save_m2m() ##修改第三张表中的数据,而你要在这二者之间是可以做,一些你想做的事情的 return render(request,"mf.html",locals())

template:

<form action="" method="post">
{% csrf_token %}
{{ obj.as_p }}
<input type="submit">
</form>

ModelForm中Meta的详解

# from  web import forms
from django.forms import Form ##Form要继承的
from django.forms import ModelForm ##ModelForm继承
from web import models
from django.forms import widgets as ws
from django import forms
from django.forms import fields class NewsModelForm(ModelForm):
email = fields.CharField() ##这个会叫把原来的email字段覆盖,变成了CharField的属性验证
pwd = fields.CharField() ##还能够增加一个News中model之外的字段,很有用。的
class Meta:
model = models.News ##里面必须要有一个model,因为他是对每个models类做增删改查的
fields = "__all__" ##指定了类,要需要指定要处理哪几个字段 __all__是全部字段
#exclude = ["email",] ##排除某个字段
labels = {"name":"名字","title":"标题"} ##显示字段的label
help_texts = {"title":"*"} ##显示字段的help_texts "*"我们代表为必填
widgets = {
"name":ws.Textarea(attrs={"class":"c1"}) ##自定义字段标签。和加属性
}
error_messages ={
"email":{"required":"必填","invalid":"格式错误"} ##自定义错误提示
}
field_classes = {
"name":forms.EmailField ##ModelForm的字段是model中的,name在model是CharField的,而我们可以更改他的验证以邮箱格式进行验证
}
localized_fields = ("ctime",) ##model中是UTC时间,显示的时候 按本地时间输出

动态生成ModelForm表单

def Dynamic_Model_Form(admin_class,form_change=True):

    class Meta:
model = admin_class.model
fields = "__all__"
##排除exclude的字段
admin_class.form_change = False ##用户前端页面是否生成p标签的判断
if form_change:
admin_class.form_change = True
exclude = admin_class.readonly_fields def __new__(cls,*args,**kwargs):
for field_name in cls.base_fields: ##字段都包含在了cls.base_fields中
filed_obj = cls.base_fields[field_name]
#添加属性
filed_obj.widget.attrs.update({'class':'form-control'}) ##
return ModelForm.__new__(cls) DyModelForm = type("Foo",(ModelForm,),{"Meta":Meta,"__new__":__new__})
return DyModelForm

Model、Form、ModelForm的比较的更多相关文章

  1. Model&Form&ModelForm拾遗

    Model&Form&ModelForm拾遗 一.Model&Form&ModelForm Model:用于用户请求数据的验证(针对性弱),但有强大的数据库操作 For ...

  2. Django的model form组件

    前言 首先对于form组件通过全面的博客介绍,对于form我们应该知道了它的大致用法,这里我们需要明确的一点是,我们定义的form与model其实没有什么关系,只是在逻辑上定义form的时候字段名期的 ...

  3. model.form使用,配合form的钩子

    一次model.form的使用记录,配合form钩子的过程 在写信息采集功能的时候,需要添加资产信息,使用modelform组件减少工作量 官网介绍:版本1.9.https://docs.django ...

  4. Django Model Form

    ModelForm ModelForm结合了Form和Model,将models的field类型映射成forms的field类型,复用了Model和Model验证, 写更少的代码,并且还实现了存储数据 ...

  5. Django之路12——form modelform formset modelformset的各种用法

      首先上结论: form适用于对单个表单的操作,并且需要对每个字段的验证规则自定义. modelform:适用于对用户提交的单个表单操作,字段可以用model中的表的字段来作为验证规则,适用于快速的 ...

  6. python3-开发进阶Django-form组件中model form组件

    Django的model form组件 这是一个神奇的组件,通过名字我们可以看出来,这个组件的功能就是把model和form组合起来,先来一个简单的例子来看一下这个东西怎么用:比如我们的数据库中有这样 ...

  7. Django 的 model form 组件

    Django 的 model form 组件 Model Form 组件的由来 之前介绍过 Django 的 Form 组件(Django的Form表单)使用方法,Form 组件能够帮我们做三件事: ...

  8. 14 Django之Form和Model Form组件

    一.什么是Form 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用 ...

  9. form modelform formset modelformset的各种用法

    form modelform formset modelformset的各种用法   首先上结论: form适用于对单个表单的操作,并且需要对每个字段的验证规则自定义. modelform:适用于对用 ...

  10. model form

    ModelForm 能允许我们通过一个 Model 直接创建一个和该模型的字段一一对应的表单,大大方便了表单操作. 下面来看一个例子. 首先我们有这样的 model: from django.db i ...

随机推荐

  1. 在dataframe添加1行(首行,或者尾部),且不覆盖

    如果直接用下面的代码添加第1行,则会覆盖掉原来的第1行. #指定位置增加一行: df.loc[0]={'a':1,'b':2} 正确方法: 新建一个同样的 dataframe, 然后合并两个dataf ...

  2. RocketMQ 单机版安装并测试

    一.安装maven 1.下载maven,http://maven.apache.org/download.cgi,并解压: -bin.tar.gz 2.修改系统环境变量,并验证: vim /etc/p ...

  3. 推荐一款在UBUNTU下使用的编辑器

    偶然的机会 ,发现了这款软件,以前一直是在用gedit编辑器,但在WINDOWS下写的文档,在ubuntu下用gedit打开后,复制有换行的问题,一直没解决,所以在网上找到了这款软件,安装使用了几天, ...

  4. 【深入理解Java虚拟机 】类加载器的命名空间以及类的卸载

    类加载器的命名空间 每个类加载器又有一个命名空间,由其以及其父加载器组成 类加载器的命名空间的作用和影响 每个类加载器又有一个命名空间,由其以及其父加载器组成 在每个类加载器自己的命名空间中不能出现相 ...

  5. A01 React+Antdesign 开发环境准备

    B站教程视频 https://www.bilibili.com/video/av38372336?from=search&seid=1131449710389099812 1 安装node.j ...

  6. CollectionUtils工具类

    CollectionUtils工具类 这篇讲的CollectionUtils工具类是在apache下的,可以使代码更加简洁和安全. 使用前需导入依赖 <dependency> <gr ...

  7. 如何理解js中的this和实际应用中需要避开哪些坑

    this是什么 this就是函数内部的关键字 看下面例子理解js中的this // 例子1 function fnOne () { console.log(this) } 'use strict' f ...

  8. Javascript Event事件中IE与标准DOM的区别

    1.事件流的区别 <body> <div> <button>点击这里</button> </div> </body> IE采用冒 ...

  9. Linux学习4-部署LAMP项目

    前言 LAMP——linux  Apache  Mysql  PHP 今天我们来学习如何在Linux部署Discuz论坛 准备工作 1.一台linux服务器,没有购买服务器的小伙伴也可以使用虚拟机,操 ...

  10. 关于Spring注解@Component、@Repository、@Service、@Controller @Resource、@Autowired、@Qualifier 解析

    1.Spring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository.@Service和 @Controller 其实这三个跟@Com ...