【原创】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 来连接 ...
随机推荐
- Linux 网络编程(IO模型)
针对linux 操作系统的5类IO模型,阻塞式.非阻塞式.多路复用.信号驱动和异步IO进行整理,参考<linux网络编程>及相关网络资料. 阻塞模式 在socket编程(如下图)中调用如下 ...
- 基于Winform、WPF等的客户端文件下载
有时候,我们用C#写一些客户端应用程序需要从服务器下载一些资源,如图片.dll.配置文件等.下面就来说一下,在Winform及WPF中如何下载文件. 我们的资源大多放在自己的网站上,或者从其他网站下载 ...
- drag & resize元素的jQuery实现
有时项目中会遇到需要拖动元素.拖拽调整元素大小的需求.大部分时候都不想自己写一遍,因为已经有很多现成的例子了.例如jqueryui提供的drag和resize.但是仅仅是为了这么小一个功能就引入一个库 ...
- Python--过滤Mysql慢日志
##================================================================## 先来个笑话: 刚交的女朋友让我去他家玩,我觉得空手不好,于是告 ...
- [nRF51822] 5、 霸屏了——详解nRF51 SDK中的GPIOTE(从GPIO电平变化到产生中断事件的流程详解)
:由于在大多数情况下GPIO的状态变化都会触发应用程序执行一些动作.为了方便nRF51官方把该流程封装成了GPIOTE,全称:The GPIO Tasks and Events (GPIOTE) . ...
- InputStream与InputStreamReader的区别
InputStream是字节流,多用于读取二进制数据 InputStreamReader是字符流,多用于读取文本文件.有不同的编码方式,如utf8等.可以在构造的时候指定编码方式. 例如,两者都有一个 ...
- jni和java对应关系
Java 类型 本地类型 描述 boolean jboolean C/C++8位整型 byte jbyte C/C++带符号的8位整型 char jchar C/C++无符号的16位整型 short ...
- AT&T Assembly on Linux
je if equal then jmp jg if the second gt the first, then jmp jge if the second ge the first, then jm ...
- jsp模仿QQ空间说说的发表
1.在文本域中输入文字(可以不添加) 2.点击添加图片(可以不添加) 3.点击发表 4.发表成功,文字和图片是超链接,点击就可以查看全部内容 5.点击图片查看原图,没有图片则不显示查看原图的超链接 主 ...
- Bootstrap~日期控制
回到目录 一个成熟的框架,日期控制是少不了的,在网上也有很多日期控制可以选择,而主框架用了bootstrap,日期控制也当前要用它自己的, 控件地址:http://www.bootcss.com/p/ ...