当前位置: 首页 > 编程日记 > 正文

Django ModelForm操作及验证

一、内容回顾

    Model- 数据库操作- 验证class A(MOdel): user = email = pwd = Form - class LoginForm(Form): email = fields.EmailField() user = pwd = - is_valid -> 每一个字段进行正则(字段内置正则)+clean_字段 -> clean(__all__) -> _post_clean - cleand_data - error --------> 推荐Form <--------- 

二、ModelForm操作及验证

Model + Form ==> ModelForm。model和form的结合体,所以有以下功能:

  • 数据验证
  • 数据库操作

model有操作数据库的字段,form验证也有那几个字段,虽然耦合度降低,但是代码是有重复的。如果利用model里的字段,那是不是form里的字段就不用写了。

1、Model + Form (之前的操作)

models.py

class UserType(models.Model): caption = models.CharField(max_length=32) class UserInfo(models.Model): username = models.CharField(max_length=32) email = models.EmailField() user_type = models.ForeignKey(to='UserType',to_field='id') 

forms.py

from django import forms
from django.forms import fields class UserInfoForm(forms.Form): # username = models.CharField(max_length=32) <-- models username = fields.CharField(max_length=32) # email = models.EmailField() <-- models email = fields.EmailField() # user_type = models.ForeignKey(to='UserType',to_field='id') <-- models user_type = fields.ChoiceField( choices=models.UserType.objects.values_list('id','caption') ) # 下面的操作是让数据在网页上实时更新。 def __init__(self, *args, **kwargs): super(UserInfoForm,self).__init__(*args, **kwargs) self.fields['user_type'].choices = models.UserType.objects.values_list('id','caption') 

index.html

<body><form action="/index/" method="POST" novalidate="novalidate"> {% csrf_token %} {{ obj.as_p }} <input type="submit" value="提交"> </form> </body> 

novalidate : HTML5输入类型和浏览器验证

如果表单中包含URLField、EmailField和其他整数字段类似,Django将使用url、email和number这样的HTML5输入类型。默认情况下,浏览器可能会对这些字段进行他们自身的验证,这些验证可能比Django的验证更严格。如果你想禁用这个行为,请设置form标签的novalidate属性,或者制定一个不同的字段,如TextInput。

2、ModelForm 基本操作

forms.py

class UserInfoModelForm(forms.ModelForm): class Meta: model = models.UserInfo # 与models建立了依赖关系 fields = "__all__" 

views.py

def index(request): if request.method == "GET": obj = UserInfoModelForm() return render(request,"index.html",{'obj':obj}) elif request.method == "POST": obj = UserInfoModelForm(request.POST) print(obj.is_valid()) # 这是方法,别忘记了加括号 print(obj.cleaned_data) print(obj.errors) return render(request,"index.html",{'obj':obj}) 

自定制字段名

如何定义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_validcleaned_dataerrors

# Form验证:UserInfoForm -> Form -> BaseForm( 包含is_valid等方法)# ModelForm验证:UserInfoModelForm -> ModelForm -> BaseModelForm -> BaseForm

3、ModelForm组件

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

注意:导入模块名(fields、widgets)和字段名重复,所以导入时要起个别名。

from django import forms
from django.forms import fields as Ffields from django.forms import widgets as Fwidgets class UserInfoModelForm(forms.ModelForm): is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput()) class Meta: model = models.UserInfo fields = '__all__' # fields = ['username','email'] # exclude = ['username'] labels = { 'username': '用户名', 'email': '邮箱', } help_texts = { 'username': '...' } widgets = { 'username': Fwidgets.Textarea(attrs={'class': 'c1'}) } error_messages = { '__all__':{ # 整体错误信息 }, 'email': { 'required': '邮箱不能为空', 'invalid': '邮箱格式错误..', } } field_classes = { # 定义字段的类是什么 # 'email': Ffields.URLField # 这里只能填类,加上括号就是对象了。 } # localized_fields=('ctime',) # 哪些字段做本地化 

4、ModelForm 数据库操作

4.1、创建数据save

如果数据验证是ok的,那么save,就直接在数据库中创建完数据了

if obj.is_valid():obj.save()      # 创建数据

在如下一对多、多对多关系中:

class UserType(models.Model): caption = models.CharField(max_length=32) class UserGroup(models.Model): name = models.CharField(max_length=32) class UserInfo(models.Model): username = models.CharField(max_length=32) email = models.EmailField() user_type = models.ForeignKey(to='UserType',to_field='id') u2g = models.ManyToManyField(UserGroup) 

这样的话,执行上面的obj.save()会在UserInfo表和多对多关系表里都增加数据。

views.py

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() # 等价以下三句 # instance = obj.save(False) # instance.save() # obj.save_m2m() return render(request,'index.html',{'obj': obj}) 

4.2、save 做了哪些操作?

save源码里:

def save(self, commit=True): """""" if commit: self.instance.save() # 指的当前model对象 self._save_m2m() # 指:保存m2m对象 else: self.save_m2m = self._save_m2m return self.instance # model 类的对象 """""" 

所以instance = obj.save(False)时,什么都不会操作。

if obj.is_valid():instance = obj.save(False)instance.save()     # 当前对象表数据创建obj.save_m2m()      # 多对多表数据创建 # 上面这三句完成的是和上面 obj.save 一样的操作。拆开就可以自定制操作了 

4.3、修改数据

修改表数据是,记得把instance信息也传进去,不然是新建数据,而不是对某行数据进行修改。
编辑用户信息,新url方式保留默认数据
urls.py

    url(r'^user_list/', views.user_list),url(r'^edit-(\d+)/', views.user_edit),

views.py

def user_list(request): li = models.UserInfo.objects.all().select_related('user_type') # 这里只能是外键,多对多字段也不可以 return render(request,'user_list.html',{'li': li}) def user_edit(request, nid): # 获取当前id对象的用户信息 # 显示用户已经存在数据 if request.method == "GET": user_obj = models.UserInfo.objects.filter(id=nid).first() mf = UserInfoModelForm(instance=user_obj) # 把默认数据传递进去 return render(request,'user_edit.html',{'mf': mf, 'nid': nid}) elif request.method == 'POST': # 数据修改的信息,给数据库的哪一行做修改? user_obj = models.UserInfo.objects.filter(id=nid).first() mf = UserInfoModelForm(request.POST,instance=user_obj) # 指定给谁做修改 if mf.is_valid(): mf.save() else: print(mf.errors.as_json()) return render(request,'user_edit.html',{'mf': mf, 'nid': nid}) 

user_list.html

<body><ul>{% for row in li %}<li>{{ row.username }} - {{ row.user_type.caption }} - <a href="/edit-{{ row.id }}/">编辑</a></li> {% endfor %} </ul> </body> 

user_edit.html

<body><form method="POST" action="/edit-{{ nid }}/"> {% csrf_token %} {{ mf.as_p }} <input type="submit" value="提交" /> </form> </body> 

5、ModelForm钩子、额外字段

数据验证钩子
从上面的FormModelForm中,他们都是继承了BaseForm,而is_valid是在BaseForm中定义的,所以ModelForm也能和Form一样使用各种钩子

额外字段
像网页上的checkbox,一个月内免登陆,用提交到数据库么?这个只需要设置session和cookie就可以了。

views.py

class UserInfoModelForm(forms.ModelForm): is_rmb = fields.CharField(widget=widgets.CheckboxInput()) # 额外字段 class Meta: model = models.UserInfo fields = '__all__' 

6、总结

    1. 生成HTML标签:class Meta: ... 2. mf = xxxModelForm(instance=ModelObj) 生成默认值 3. 额外的标签, is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput()) 4. 各种验证 is_valid() -> 各种钩子... 5. mf.save() # 或 instance = mf.save(False) instance.save() mf.save_m2m() 

ModelForm因为model和form耦合太密切,所以一般写小程序用它。



作者:马小跳_
链接:https://www.jianshu.com/p/dee5806b27a1
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

转载于:https://www.cnblogs.com/floodwater/p/10019284.html

相关文章:

matlab外部接口简介

1、MATLAB外部接口主要包括3部分内容&#xff1a; (1)、MEX文件&#xff1a;外部程序调用接口&#xff1b; MEX文件是MATLAB解释器可以自动加载和运行的动态链接过程&#xff0c;MATLAB可以像调用内部函数一样调用它们。用户通过MEX文件可以完成以下功能&#xff1a; 可以在…

IE调试网页之一:F12 开发人员工具简介

F12 开发人员工具是可帮助生成和调试网页的一套工具。 编写出色的网页需要编码知识以及适当的工具来发现和调试难免会出现的问题。Windows Internet Explorer 9 提供所呈现代码的视图&#xff0c;F12 工具提供 Internet Explorer 9 如何在代码级别上解释这些页面的视图。F12 工…

100万奖金池,这不仅仅是场比赛

这&#xff0c;不仅仅是场比赛&#xff0c;更是对最前沿领域的共同探索2019 E起AI&#xff01;2019年度的大赛&#xff0c;由香港科大商学院和香港科大商学院内地办事处主办&#xff0c;由香港科大EMBA校友企业安讯科技冠名&#xff0c;将围绕人工智能领域的创新及运用展开赛事…

举例说明使用MATLAB Coder从MATLAB生成C/C++代码步骤

MATLAB Coder可以从MATLAB代码生成独立的、可读性强、可移植的C/C代码。 使用MATLAB Coder产生代码的3个步骤&#xff1a;准备用于产生代码的MATLAB算法&#xff1b;检查MATLAB代码的兼容性(有些matlab代码语句并不能生成c/c代码)&#xff1b;产生最终使用的源代码或MEX。 利…

媒体智能应用落地靠5G,视频社交需要想象力

作者简介&#xff1a;卢迪&#xff0c;中国传媒大学新媒体研究院书记、副教授、硕士研究生导师。人工智能正逐渐成为重要的基础设施&#xff0c;在与各行各业传统领域紧密结合的基础上对社会生产、生活方式带来深刻的影响。中央多次强调媒体融合&#xff0c;“要探索将人工智能…

堆栈的链表实现

2019独角兽企业重金招聘Python工程师标准>>> /** stack3.c** Created on: Dec 6, 2012* Author: fsxchen* 链式结构的栈*/ #include #include #include #include typedef struct StackNode //节点结构体 {int data; //存放数…

registry ---------仓库 -----------------镜像

registry --------->仓库 ----------------->镜像    本地镜像都保存在宿主机下 :    /var/lib/docker/containers    镜像从仓库下载下来.镜像保存在仓库中,而仓库存在于Registry中.    Docker Hub 中有两种类型的仓库:    用户库:    用户仓库…

BigBiGAN问世,“GAN父”都说酷的无监督表示学习模型有多优秀?

作者 | Jeff Donahue、Karen Simonyan 译者 | Lucy、一一出品 | AI开发者大本营&#xff08;ID:rgznai100&#xff09;众所周知&#xff0c;对抗训练生成模型&#xff08;GAN&#xff09;在图像生成领域获得了不凡的效果。尽管基于GAN的无监督学习方法取得了初步成果&#xff0…

技术人生:与其鸟宿檐下,不如击翅风雨

人生途中&#xff0c;有些是无法逃避的&#xff0c;比如命运&#xff1b;有些是无法更改的&#xff0c;比如情缘&#xff1b;有些是难以磨灭的&#xff0c;比如记忆&#xff1b;有些是难以搁置的&#xff0c;比如爱恋……与其被动地承受&#xff0c;不如勇敢地面对&#xff1b;…

C++递归用法

转自&#xff1a;http://bbs.ikaka.com/showtopic-664019.aspx 简单谈谈C 递归的思想实现以及和循环的关系 很多初学者往往对递归迷惑不解&#xff0c;也在这上面花了不少的时间。其实教材上的例子很经典&#xff0c;只是它说的有一些唠叨了。初学者会看的头大的。编程是解决…

java导入excle表格,并且对表格进行相应的修改,并对表格数据进行整理,最后导出本地表格等一系列...

1.首先创建一个java项目 完成效果如下图所示 2.导入以下jar包 3.代码如下 其中行和列的操作是根据需求自动划分的 复制代码1 public class auto_date {2 private static List<List<String>> readExcel(File file) throws Exception {3 // 创建输入流&#xff0c;读…

RetinaFace,最强开源人脸检测算法

作者 | CV君 来源 | 我爱计算机视觉&#xff08;ID&#xff1a;aicvmlaicvmlaicvml&#xff09;人脸检测为目标检测的特例&#xff0c;是商业化最早的目标检测算法&#xff0c;也是目前几乎各大 CV 方向 AI 公司的必争之地。WIDER FACE 数据集是由香港中文大学发布的大型人脸数…

OpenCV中cvBlobsLib的编译与使用

OpenCV的cvBlobsLib库的作用类似于matlab中的regionprops函数。 cvBlobsLib库的编译&#xff1a; 首先从http://opencv.willowgarage.com/wiki/cvBlobsLib#Blobextractionlibrary下载最新的v8.3版本的源代码&#xff0c;其次机子上要装有OpenCV1.0的环境&#xff0c;从http:/…

AWS开源Firecracker,一种运行多租户容器服务的新虚拟化技术

现在的技术环境下&#xff0c;容器具有快速启动时间和高密度&#xff0c;VM可以对硬件虚拟化&#xff0c;具有更好的安全性&#xff0c;并对工作负载具有更好的隔离性。容器和VM的特性现在还不可兼得。 现在AWS开源了Firecracker&#xff0c;一种利用KVM的新虚拟化技术&#xf…

python urllib2 开启调试

2019独角兽企业重金招聘Python工程师标准>>> 发一段在网上看见. USING HTTPLIB.HTTPCONNECTION.SET_DEBUGLEVEL() WITH URLLIB2 Posted on October 1, 2007, 9:52 pm, by jamiegrove, under python. I’ve been trying to get the debug level turned on in urll…

从发展滞后到不断突破,NLP已成为AI又一燃爆点?

作者 | 刘家俊&#xff0c;一览群智CTO责编 | Jane出品 | AI科技大本营&#xff08;ID &#xff1a;rgznai100&#xff09;自然语言处理&#xff1a;人工智能连接主义复兴浪潮中的下一个突破口AI 行业应用是一片新的大陆&#xff0c;深度学习作为新大陆的基石&#xff0c;经历了…

matlab最小分类错误全局二值化算法

转自&#xff1a;http://download.csdn.net/detail/hupeng810/1511870 function imagBW kittlerMet(imag) % KITTLERMET binarizes a gray scale image imag into a binary image % Input: % imag: the gray scale image, with black foreground(0), and white % bac…

XShell连接Deepin

为什么80%的码农都做不了架构师&#xff1f;>>> 先让deepin安装openssh sudo apt-get install openssh-serverchkconfig ssh on 转载于:https://my.oschina.net/enzo/blog/110518

第三届“达观杯”文本智能信息抽取挑战赛丰厚奖金,群英集结,等你来战!...

近日&#xff0c;第三届“达观杯”文本智能信息抽取挑战赛正式上线启动&#xff08;点击阅读原文&#xff0c;跳转报名页面&#xff09;&#xff0c;6月28日至8月31日&#xff0c;面向所有参赛选手开放竞赛结果提交。本届“达观杯”的任务是信息抽取。“达观杯”大赛由国内文本…

Spline interpolation and Savitzki-Golay smoothing

转自&#xff1a;http://octave.1599824.n4.nabble.com/Spline-interpolation-and-Savitzki-Golay-smoothing-td1675136.html ## natural-cubic-spline interpolation ## usage: yspline spline(x,y,xspline) ## example: ## x 0:10; y sin(x); ## xspline 0:0.1:10; y…

SpringBoot实现热部署(修改class不需要重启)

热部署: devtools可以实现页面热部署(即页面修改后会立即生效&#xff0c; 这个可以直接在application.properties文件中配置spring.thymeleaf.cachefalse来实现) 实现类文件热部署(类文件修改后不会立即生效),实现对属性文件的热部署。 注意&#xff1a;因为采用的虚拟机机制&…

Oracle中查看表空间的使用率的脚本

如题&#xff1a; select f.tablespace_name tablespace_name, round((d.sumbytes / 1024 / 1024 / 1024), 2) total_g, round(f.sumbytes / 1024 / 1024 / 1024, 2) free_g, round((d.sumbytes - f.sumbytes) / 1024 / 1024 / 1024, 2) used_g, round((d.sumbytes - f.sumbyte…

vue实现多个元素或多个组件之间动画效果

2019独角兽企业重金招聘Python工程师标准>>> 多个元素的过渡 <style>.v-enter,.v-leave-to{opacity: 0;}.v-enter-acitve,.v-leave-active{opacity: opacity 1s;} </style> <div idapp><transition><div v-ifshow>hello world</di…

干货 | 20个教程,掌握时间序列的特征分析(附代码)

作者 | Selva Prabhakaran 译者 | Tianyu责编 | Jane出品 | AI科技大本营&#xff08;ID: rgznai100&#xff09;【导语】时间序列是指以固定时间为间隔的序列值。本篇教程将教大家用 Python 对时间序列进行特征分析。1、什么是时间序列&#xff1f;时间序列是指以固定时间为间…

利用OpenCV求取图像的重心

转自&#xff1a;http://blog.csdn.net/lxiaoxiaot/article/details/6539834 不规则区域的矩&#xff0c;表示把一个归一化的灰度级图像函数理解为一个二维随机变量的概率密度。 这个随机变量的属性可以用统计特征--矩&#xff08;Moments&#xff09;来描述。通过假设非零的像…

C++中Ansi、Unicode、UTF8字符串之间的转换和写入

转自: http://dark0729.blogbus.com/logs/51496111.html Ansi字符串我们最熟悉&#xff0c;英文占一个字节&#xff0c;汉字2个字节&#xff0c;以一个\0结尾&#xff0c;常用于txt文本文件 Unicode字符串&#xff0c;每个字符(汉字、英文字母)都占2个字节&#xff0c;以2个连…

MyBatis的扩展点(plugins)

2019独角兽企业重金招聘Python工程师标准>>> 1、mybatis扩展点plugins mybatis的扩展是通过拦截器Interceptor来实现的&#xff0c;本质上就是JDK的动态代理&#xff0c;所以它只能对接口进行拦截&#xff0c;mybatis可以对以下四个接口类型进行拦截&#xff0c;也就…

linux中使用CST时间

GMT(Greenwich Mean Time&#xff0c;格林威治标准时间): 是指位于英国伦敦郊区的格林尼治天文台的标准时间&#xff0c;因为本初子午线被定义在通过那里的经线。 UTC(Universal Time/Temps Cordonn 世界标准时间)CST(Central Standard Time 國家標準時間&#xff0c;一說中原標…

到「黄埔学院」去:打造AI首席架构师,第二期限量招募!

今年 1 月&#xff0c;百度联合“深度学习技术及应用国家工程实验室”成立黄埔学院&#xff0c;旨在为产业培养第一批“首席AI架构师”。黄埔学院一期学员历时半年的学习和交流&#xff0c;6 月 16 日&#xff0c;黄埔学院一期学员迎来了毕业典礼&#xff0c;并在 7 月百度 AI开…

linux守护进程的创建

下面的完成了这样一个功能&#xff0c;创建一个守护进程&#xff0c;每个一秒在/tmp目录下的文件peng.txt中记录当前系统时间。 一、守护进程 守护进程是linux中的后台服务进程&#xff0c;在系统启动时开始运行&#xff0c;在系统关闭时终止。Linux系统中的大多数服务进程都是…