【原创】Django-ORM进阶
基础部分已经写完:【原创】Django-ORM基础
以下部分将对表与表之间的关联操作做以介绍
models.py
#_*_coding:utf-8_*_
from django.db import models # Create your models here. class Colors(models.Model):
colors=models.CharField(u'颜色',max_length=10)
def __unicode__(self):
return self.colors class Ball(models.Model):
color=models.OneToOneField("Colors") #与颜色表为一对一,颜色表为母表
description=models.CharField(u'描述',max_length=10)
def __unicode__(self):
return self.description class Clothes(models.Model):
color=models.ForeignKey("Colors") #与颜色表为外键,颜色表为母表
description=models.CharField(u'描述',max_length=10)
def __unicode__(self):
return self.description class Child(models.Model):
name=models.CharField(u'姓名',max_length=10)
favor=models.ManyToManyField('Colors') #与颜色表为多对多
models.py
一对一
查:
#子表查询母表,找到红球对应的颜色
#写法1:
print(models.Ball.objects.get(description="红球").color.colors) #返回红,通过子表查询母表,写法:"子表对象.母表表名的小写.母表字段名" ;通过Ball表查到description为"红球",查找到对应colors
#写法2,反向从母表入手:
print(models.Colors.objects.get(ball__description="红球").colors) #返回红,通过子表查询母表,但形式上是从母表对象自身直接获取字段,写法:"母表.objects.get(子表名小写__子表字段="xxx").母表字段名" ;效果和上边完全一致,另一种形式 #母表查询子表,找到红色对应的球的名字
#写法1:
print(models.Colors.objects.get(colors="红").ball.description) #返回红球,通过母表查询子表,写法:"母表对象.子表表名的小写.子表字段名";找到颜色为红色的Ball的description
#写法2,反向从子表入手:
print(models.Ball.objects.get(color__colors="红").description) #返回红球,通过母表查询子表,但形式上是从子表对象自身直接获取字段,写法:"子表.objects.get(一对一的子表字段__母表字段="xxx").子表字段";效果和上边完全一致,另一种形式
增:
#添加一种颜色黑,并添加黑球
color_obj=models.Colors.objects.create(colors="黑") #先在母表中创建颜色,并实例化给颜色表对象
models.Ball.objects.create(color=color_obj,description="黑球") #更新Ball表,color字段为颜色表对象,添加description字段
#增添数据的三种写法:
#写法1:
color_obj=models.Colors.objects.create(colors="黑")
models.Ball.objects.create(color=color_obj,description="黑球")
#写法1补充:
color_id=models.Colors.objects.create(colors="黑").id
models.Ball.objects.create(color_id=color_id,description="黑球")
#写法2:
color_obj=models.Colors.objects.create(colors="黑")
ball_obj=models.Ball(color=color_obj,description="黑球")
ball_obj.save()
#写法3(字典导入):
color_obj=models.Colors.objects.create(colors="黑")
ball_dic={'description':"黑球"}
models.Ball.objects.create(color=color_obj,**ball_dic)
改:
color_obj=models.Colors.objects.get(colors="黑") #.get()等同于.filter().first()
color_obj.colors="灰"
color_obj.save()
models.Ball.objects.filter(description="黑球").update(color=color_obj,description="灰球") #update(),delete()是QuerySet的方法
#更新一条数据
color_obj=models.Colors.objects.get(colors="黑")
color_obj.colors="灰"
color_obj.save()
#更新多条数据,把满足条件的球的description都变为灰球
#写法1:
models.Ball.objects.filter(color__colors="红").update(description="灰球")
#写法2:
up_dic={"description":"灰球"}
models.Ball.objects.filter(id__gt=0).update(**up_dic)
删:
models.Ball.objects.get(description="灰球").delete() #对象和QuerySet都有方法delete()
models.Colors.objects.filter(colors="灰").delete() models.Colors.objects.all().delete() #清空一张表
一对多(外键)
查:
#外键表联合查询: #外键子表查询母表,与一对一子表查询母表形式一致
#找到红裤衩所属的颜色表中的颜色--返回:红
#写法1:
print(models.Clothes.objects.get(description="红内裤").color.colors) #返回红,通过子表查询母表,写法:"子表对象.母表表名的小写.母表字段名" ;通过Clothes表查到description为"红内裤",查找到对应colors
#写法2,反向从母表入手:
print(models.Colors.objects.get(clothes__description="红内裤").colors) #返回红,通过子表查询母表,但形式上是从母表对象自身直接获取字段,写法:"母表.objects.get(子表名小写__子表字段="xxx").母表字段名" ;效果和上边完全一致,另一种形式 #外键母表查询子表,与一对一形式不同,因为母表为"多",不能像一对一一样通过.get().子表.子表字段的方式获取,但与多对多母表查询子表一致
#找到颜色为红的所有服装--返回:[<Clothes: 红内衣>, <Clothes: 红内裤>]
#写法1:
color_obj=models.Colors.objects.get(colors="红")
print(color_obj.clothes_set.all()) #注意:子表小写_set的写法,它实际上是一个QuerySet,可以用update,delete,all,filter等方法
#写法2:
print(models.Clothes.objects.filter(color=models.Colors.objects.get(colors="红")))
#写法2简便写法(推荐):
print(models.Clothes.objects.filter(color__colors="红")) #写法:filter(子表外键字段__母表字段='过滤条件')
#写法3:
color_id=models.Colors.objects.get(colors="红").id #通过母表获取到颜色为红的id
print(models.Clothes.objects.filter(color_id=color_id)) #filter得到QuerySet,写法:filter(子表外键字段_母表主键=母表主键对象)
print(models.Clothes.objects.filter(color=models.Colors.objects.get(colors="红")).values('color__colors','description')) #获取子表的description字段,和母表的colors字段,获取母表字段写法: 子表外键字段名__母表字段名--适用于values()或filter()
#简写形式补充:
print(models.Clothes.objects.filter(color__colors="红").values('color__colors','description'))
#返回:
[{'description': u'\u7ea2\u5185\u8863', 'color__colors': u'\u7ea2'}, {'description': u'\u7ea2\u5185\u88e4', 'color__colors': u'\u7ea2'}]
#如果不加values(),返回的是[<Clothes: 红内衣>, <Clothes: 红内裤>]这样一个QuerySet集合,通过values可以形成一个列表,列表中的每一个元素是一个字典,可以通过list()将ValuesQeurySet转化为列表,之后返回给templates
#另外可通过.values_list()将QuerySet转化为ValuesListQuerySet。返回:[(u'\u7ea2', u'\u7ea2\u889c\u5b50'), (u'\u7ea2', u'\u7ea2\u889c\u5b50')]
#得到的是一个列表,列表中是多个元组,每个元组是ValuesQuerySet中字典的value,常用于从models里将数据取出后动态添加到前端模板中的select选项中。
#通过forms.py从models取值传给前端select选项,需重启django后,select选项才能更新,可在定义form时,添加如下关键字保障动态更新select选项
#forms.py
from django import forms
from test1 import models
class ClothesForm(forms.Form):
color=forms.IntegerField(required=True,widget=forms.Select(),)
def __init__(self,*args,**kwargs): #定义这个关键字段,当使用form时,colors表新增了颜色,前端ClothesForm的color字段的选项会自动更新
super(ClothesForm, self).__init__(*args,**kwargs)
self.fields['color'].widget.choices=models.Colors.objects.all().order_by('id').values_list('id','colors')
#增添子表数据,形式与一对一一致
#添加颜色为绿的服装:绿裤头
#方法1:
models.Clothes.objects.create(color=models.Colors.objects.get(colors="绿"),description="绿裤头")
#方法1补充:
models.Clothes.objects.create(color_id=models.Colors.objects.get(colors="绿").id,description="绿裤头")
#方法2:
c_obj=models.Clothes(color=models.Colors.objects.get(colors="绿"),description="绿裤头")
c_obj.save()
#方法3:字典方式录入..参考一对一
改:
#颜色为红的服装,description都更新为红袜子
#写法1:
models.Clothes.objects.filter(color__colors="红").update(description="红袜子")
#写法2:
models.Clothes.objects.filter(color_id=models.Colors.objects.get(colors="红").id).update(description="红袜子")
#写法3:
colors_obj=models.Colors.objects.get(colors="红")
colors_obj.clothes_set.filter(id__gte=1).update(description="红袜子")
#其他写法参照一对一的修改和外键的查询
删:
models.Clothes.objects.get(description="灰裙子").delete() #对象和QuerySet都有方法delete()
models.Colors.objects.filter(colors="灰").delete()
多对多
查:
#多对多子表查询母表,查找小明喜欢哪些颜色--返回:[<Colors: 红>, <Colors: 黄>, <Colors: 蓝>]
#与一对多子表查询母表的形式不同,因为一对多,查询的是母表的“一”;多对多,查询的是母表的“多”
#写法1:
child_obj=models.Child.objects.get(name="小明") #写法:子表对象.子表多对多字段.过滤条件(all()/filter())
print(child_obj.favor.all())
#写法2,反向从母表入手:
print(models.Colors.objects.filter(child__name="小明")) #母表对象.filter(子表表名小写__子表字段名="过滤条件") #多对多母表查询子表,查找有哪些人喜欢黄色--返回:[<Child: 小明>, <Child: 丫蛋>]
#与一对多母表查询子表的形式完全一致,因为查到的都是QuerySet,一对多和多对多,都是在查询子表的“多”
#写法1:
color_obj=models.Colors.objects.get(colors="黄")
print(color_obj.child_set.all())
#写法2:
print(models.Child.objects.filter(favor=models.Colors.objects.get(colors="黄")))
#写法2简便写法(推荐):
print(models.Child.objects.filter(favor__colors="黄")) #写法:filter(子表外键字段__母表字段='过滤条件')
#写法3:
color_id=models.Colors.objects.get(colors="黄").id #通过母表获取到颜色为红的id
print(models.Child.objects.filter(favor=color_id)) #filter得到QuerySet,写法:filter(子表外键字段=母表主键对象),此处和一对多略有不同,是子表外键字段而不是外键字段_母表主键
增与改(增添子表或母表数据参照一对一的增,多对多重点在于关系表的对应关系变更):
#添加子表关联关系
#添加小呆并让他喜欢所有颜色
#写法1:
child_obj=models.Child.objects.create(name="小呆") #如果是已有用户,使用.get()
colors_obj=models.Colors.objects.all() #创建颜色表的所有颜色QuerySet对象
child_obj.favor.add(*colors_obj) #添加对应关系,将小呆和所有颜色进行关联,写法:子表对象.子表多对多字段.add(*QuerySet对象)
#写法2:
child_obj=models.Child.objects.get(name="小呆")
colors_obj=models.Colors.objects.all()
child_obj.favor=colors_obj
child_obj.save()
#让小呆喜欢黄色和蓝色(2种写法和上边一致,只展示一种写法)
child_obj=models.Child.objects.get(name="小呆")
colors_obj=models.Colors.objects.filter(colors__in=["蓝","黄"]) #models默认只能用这种方式得到并集,如需更复杂的过滤逻辑,需使用模块Q
child_obj.favor.clear() #清空小呆已经喜欢的颜色
child_obj.favor.add(*colors_obj) #add是追加模式,如果当前小呆已经喜欢绿色,那么执行后,小呆会额外喜欢蓝,黄
#让小呆喜欢绿色(2种写法和上边一致,只展示一种写法)
child_obj=models.Child.objects.get(name="小呆")
colors_obj=models.Colors.objects.get(colors="绿")
child_obj.favor.clear()
child_obj.favor.add(colors_obj) #此处没有* #添加母表关联关系
#让喜欢蓝色的人里添加小呆,可以用上边的方法,一个效果,让小呆喜欢蓝色,下边介绍反向插入(从母表入手)的写法
child_obj=models.Child.objects.get(name="小呆")
colors_obj=models.Colors.objects.get(colors="蓝")
colors_obj.child_set.add(child_obj) #从colors表插入小呆,写法:母表对象.子表名小写_set.add(子表对象)。 让喜欢蓝色的child_set集合添加name="小呆"
#让所有人都喜欢蓝色
children_obj=models.Child.objects.all()
colors_obj=models.Colors.objects.get(colors="蓝")
colors_obj.child_set.add(*children_obj)
#关于_set写法,是否已经有些晕了,究竟什么时候使用_set,简单记忆,只有子表才有"子表名小写_set"的写法,得到的是一个QuerySet集合,后边可以接.add(),.remove(),.update(),.delete(),.clear()
#另外备注一下,colors_obj.child_set.clear()是让所有人喜欢的颜色里去掉蓝色,colors_obj.child_set.all().delete()是删除.child_set的所有人
删:
删除多对多表关系 :
#删除子表与母表关联关系
#让小呆不喜欢任何颜色
#写法1:
child_obj=models.Child.objects.get(name="小呆")
colors_obj=models.Colors.objects.all()
child_obj.favor=''
child_obj.save()
#写法2:
child_obj=models.Child.objects.get(name="小呆")
colors_obj=models.Colors.objects.all()
child_obj.favor.remove(*colors_obj)
#写法3:
child_obj=models.Child.objects.get(name="小呆")
child_obj.favor.clear()
#其他例子参照多对多的增与改案例,这里不做举例 #删除母表与子表关联关系
#让所有人不再喜欢蓝色
#写法1:
children_obj=models.Child.objects.all()
colors_obj=models.Colors.objects.get(colors="蓝")
colors_obj.child_set.remove(*children_obj)
#写法2:
colors_obj=models.Colors.objects.get(colors="蓝")
colors_obj.child_set.clear()
删除多对多表数据:
#删除子表数据
#喜欢蓝色的所有人都删掉
colors_obj=models.Colors.objects.get(colors="蓝")
colors_obj.child_set.all().delete() #注意有.all()
#删除所有child
models.Child.objects.all().delete()
删除母表数据:
默认情况下,如此例中,删除“红”色,那么子表与颜色表是一对一或外键关系的,子表对应数据会自动删除,如:红球,红内裤
与颜色表是多对多关系的话,不会自动删除喜欢红色的人,而是去掉红色已选
如果想让与母表外键关联的子表在删除外键之后依旧可以保留子表数据,需要子表建表时加入以下字段:
class Clothes(models.Model):
color=models.ForeignKey("Colors",null=True,on_delete=models.SET_NULL)) #可为空,如果外键被删后,子表数据此字段置空而不是直接删除这条数据,同理也可以SET_DEFAULT,需要此字段有默认值
description=models.CharField(u'描述',max_length=10)
choice
#choices相当于实现一个简化版的外键,外键的选项不能动态更新,如可选项目较少,可以采用
#先在models添加choices字段
class Child(models.Model):
sex_choice=((0,"男"),(1,"女"))
name=models.CharField(u'姓名',max_length=10)
favor=models.ManyToManyField('Colors') #与颜色表为多对多
sex=models.IntegerField(choices=sex_choice,default=0)
def __unicode__(self):
return self.name #在views.py中调用
child_obj=models.Child.objects.get(name="小呆")
print(child_obj.sex) #返回0或1
print(child_obj.get_sex_display()) #返回男或女
【原创】Django-ORM进阶的更多相关文章
- Django orm进阶查询(聚合、分组、F查询、Q查询)、常见字段、查询优化及事务操作
Django orm进阶查询(聚合.分组.F查询.Q查询).常见字段.查询优化及事务操作 聚合查询 记住用到关键字aggregate然后还有几个常用的聚合函数就好了 from django.db.mo ...
- 9.14.16 Django ORM进阶用法
2018-9-14 14:26:45 ORM 练习题 : http://www.cnblogs.com/liwenzhou/articles/8337352.html 2018-9-14 21:1 ...
- Django - ORM - 进阶
一.多表操作 创建模型 实例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是 ...
- Django中的ORM进阶操作
Django中的ORM进阶操作 Django中是通过ORM来操作数据库的,通过ORM可以很easy的实现与数据库的交互.但是仍然有几种操作是非常绕也特别容易混淆的.于是,针对这一块,来一个分类总结吧. ...
- 【python】-- Django ORM(进阶)
Django ORM(进阶) 上一篇博文简述了Django ORM的单表操作,在本篇博文中主要简述Django ORM的连表操作. 一.一对多:models.ForeignKey() 应用场景:当一张 ...
- django框架基础-ORM进阶-长期维护
############### ORM进阶---contenttype ################ 设计思路: """ 路飞有两种课,专题课和学位课, ...
- Django ORM操作及进阶
一般操作 看专业的官网文档,做专业的程序员! 必知必会13条 <1> all(): 查询所有结果 <2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 ...
- django 2 ORM操作 ORM进阶 cookie和session 中间件
ORM操作 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述 ...
- Python之路【第十七篇】:Django【进阶篇 】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
- Python之路【第十七篇】:Django【进阶篇】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
随机推荐
- cefsharp开发实例1
做了几年.NET开发,基本都是搞WEB居多,以前也搞过一个winform项目,虽然很把界面拼接出来了,但是感觉有点痛苦,改动的时候又要改动一大堆代码.最近又要搞个桌面软件,试着搜索了下html做界面方 ...
- 【AspNetCore】【WebApi】扩展Webapi中的RouteConstraint中,让DateTime类型,支持时间格式化(DateTimeFormat)
扩展Webapi中的RouteConstraint中,让DateTime类型,支持时间格式化(DateTimeFormat) 一.背景 大家在使用WebApi时,会用到DateTime为参数,类似于这 ...
- css选择器优先级全解析
这样一个问题: <!doctype html> <htmllang="en"> <head> <metacharset="UTF ...
- Unity3d使用经验总结 数据驱动篇
我这里说的数据驱动,不是指某种框架,某种结构,或者某种编码方式. 我要说的,是一种开发方式. 大家都知道,U3D中,我们可以为某个对象编写一个脚本,然后将这个脚本挂在对象上,那这个对象就拥有了相应的能 ...
- Windows上帝模式,上帝应该就是这样使用Windows的
Windows上帝模式(Windows Master Control Panel)由来已久,最早是从Win7优化大湿里看到的一个选项,开启后在桌面生成一个图标,点进去后里面包含了几乎全部Windows ...
- 目前在做的一个web应用程序的前端选型
最近进入了一个新的项目组,要新起一个项目.这个Web项目是一个企业内部使用的系统,主要用来记录.追踪.管理潜在客户的数据.该系统有以下特点: 需要支持IE10及以上版本: 后端采用micro serv ...
- C# socket编程实践——支持广播的简单socket服务器
在上篇博客简单理解socket写完之后我就希望写出一个websocket的服务器了,但是一路困难重重,还是从基础开始吧,先搞定C# socket编程基本知识,写一个支持广播的简单server/clie ...
- java gc的考察
参考http://www.cnblogs.com/mazj611/p/3481610.html 看了很多博客.书, 仍然有所不懂.很多看过即忘记.实在要不得. 我们可以通过jstat获取gc情况 js ...
- java 堆栈分析4
jprofiler ,又是一款好工具... —— 不过显然,我觉得有了jvisualvm就足够了,难道它会比jvisualvm还强大很多!?? 什么时候需要它呢?它有什么特别好用的地方吗? 带来什么方 ...
- VUE 意淫笔记
caihg Vue.js 递归组件实现树形菜单 最近看了 Vue.js 的递归组件,实现了一个最基本的树形菜单. 项目结构: main.js 作为入口,很简单: 1 2 3 4 5 6 7 8 9 i ...