Django模型层的多表操作(2)
一基于双划线的跨表查询
Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系。要做跨关系查询,就使用两个下划线来链接模型(model)间关联字段的名称,直到最终链接到你想要的model 为止。
'''正向查询按字段,反向查询按表名小写用来告诉ORM引擎join哪张表 '''
一对多查询
# 练习: 查询苹果出版社出版过的所有书籍的名字与价格(一对多)# 正向查询 按字段:publishqueryResult=Book.objects.filter(publish__name="苹果出版社").values_list("title","price")# 反向查询 按表名:bookqueryResult=Publish.objects.filter(name="苹果出版社").values_list("book__title","book__price")
多对多查询
# 练习: 查询alex出过的所有书籍的名字(多对多)# 正向查询 按字段:authors:queryResult=Book.objects.filter(authors__name="yuan").values_list("title")# 反向查询 按表名:bookqueryResult=Author.objects.filter(name="yuan").values_list("book__title","book__price")
一对一查询
# 查询alex的手机号# 正向查询ret=Author.objects.filter(name="alex").values("authordetail__telephone")# 反向查询ret=AuthorDetail.objects.filter(author__name="alex").values("telephone")
进阶练习(连续跨表)
# 练习: 查询人民出版社出版过的所有书籍的名字以及作者的姓名# 正向查询queryResult=Book.objects.filter(publish__name="人民出版社").values_list("title","authors__name")# 反向查询queryResult=Publish.objects.filter(name="人民出版社").values_list("book__title","book__authors__age","book__authors__name")# 练习: 手机号以151开头的作者出版过的所有书籍名称以及出版社名称 # 方式1:queryResult=Book.objects.filter(authors__authorDetail__telephone__regex="151").values_list("title","publish__name")# 方式2: ret=Author.objects.filter(authordetail__telephone__startswith="151").values("book__title","book__publish__name")
related_name
反向查询时,如果定义了related_name ,则用related_name替换表名,例如:
1
|
publish = ForeignKey(Blog, related_name = 'bookList' )
|
# 练习: 查询人民出版社出版过的所有书籍的名字与价格(一对多) # 反向查询 不再按表名:book,而是related_name:bookList queryResult=Publish.objects.filter(name="人民出版社").values_list("bookList__title","bookList__price")
二.聚合查询和分组查询
1.聚合
aggregate(*args, **kwargs)
aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定一个名称,可以向聚合子句提供它。
# 计算所有图书的平均价格>>> from django.db.models import Avg>>> Book.objects.all().aggregate(Avg('price')){'price__avg': 34.35}
如果希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:
>>> from django.db.models import Avg, Max, Min >>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price')) {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}
# 查询所有书籍的平均价格from django.db.models import Avg,Max,Sum,Min,Countret=Book.objects.all().aggregate(priceAvg=Avg("price"))print(ret) # {'priceAvg': 142.0} # 查询所有书籍的个数 ret=Book.objects.all().aggregate(c=Count(1)) print(ret) # {'c': 4}
2.分组
annotate()为调用的QuerySet中每一个对象都生成一个独立的统计值(统计方法用聚合函数)。
单表分组查询
查询每一个部门名称以及对应的员工数emp:id name age salary dep 1 alex 12 2000 销售部 2 egon 22 3000 人事部 3 wen 22 5000 人事部sql语句: select dep,Count(*) from emp group by dep;ORM: emp.objects.values("dep").annotate(c=Count("id")
#查询书籍表每一个出版社id以及对应的书籍个数 key: annotate()前values哪一个字段就按哪一个字段group by ret=Book.objects.values("publish_id").annotate(c=Count(1)) print(ret)# 查询每一个部门的名称以及对应员工的平均薪水ret=Emp.objects.values("dep").annotate(avg_salary=Avg("salary"))print(ret) # [{'dep': '教学部', 'avg_salary': 2500.0}, {'dep': '保洁部', 'avg_salary': 3500.0}, {'dep': '保安部', 'avg_salary': 4000.0}]># 查询每一个省份的名称以及对应的员工最大年龄 ret=Emp.objects.values("pro").annotate(max_age=Max("age")) print(ret) # <QuerySet [{'pro': '山东省', 'max_age': 123}, {'pro': '河南省', 'max_age': 23}, {'pro': '河北省', 'max_age': 56}]>
跨表的分组查询
查询每一个部门名称以及对应的员工数emp:id name age salary dep_id 1 alex 12 2000 1 2 egon 22 3000 2 3 wen 22 5000 2depid name 1 销售部 2 人事部emp-dep:id name age salary dep_id id name 1 alex 12 2000 1 1 销售部 2 egon 22 3000 2 2 人事部 3 wen 22 5000 2 2 人事部sql语句: select dep.name,Count(*) from emp left join dep on emp.dep_id=dep.id group by dep.idORM: dep.objetcs.values("id").annotate(c=Count("emp")).values("name","c")
class Emp(models.Model):name=models.CharField(max_length=32)age=models.IntegerField()salary=models.DecimalField(max_digits=8,decimal_places=2)dep=models.CharField(max_length=32)province=models.CharField(max_length=32)
创建Emp表
总结 :跨表分组查询本质就是将关联表join成一张表,再按单表的思路进行分组查询。
# 查询每一个出版社的名称以及对应的书籍平均价格 ret=Publish.objects.values("name","email").annotate(avg_price=Avg("book__price")) print(ret) # <QuerySet [{'name': '苹果出版社', 'avg_price': 117.0}, {'name': '橙子出版社', 'avg_price': 112.0}, {'name': '西瓜出版社', 'avg_price': 222.0}]># 查询每一个作者的名字以及出版的书籍的最高价格ret=Author.objects.values("pk","name").annotate(max_price=Max("book__price"))print(ret)# 查询每一个书籍的名称以及对应的作者的个数 ret=Book.objects.values("title").annotate(c=Count("authors")) print(ret) # <QuerySet [{'title': 'python', 'authors__count': 2}, {'title': 'linux', 'authors__count': 1}, {'title': 'go', 'authors__count': 1}, {'title': 'java', 'authors__count': 0}]>
三.F查询与Q查询
F查询
在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?
Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
1
2
3
4
|
# 查询评论数大于收藏数的书籍
from django.db.models import F
Book.objects. filter (commnetNum__lt = F( 'keepNum' ))
|
Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。
1
2
|
# 查询评论数大于收藏数2倍的书籍
Book.objects. filter (commnetNum__lt = F( 'keepNum' ) * 2 )
|
修改操作也可以使用F函数,比如将每一本书的价格提高30元:
1
|
Book.objects. all ().update(price = F( "price" ) + 30 )
|
Q查询
filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象。
1
2
|
from django.db.models import Q
Q(title__startswith = 'Py' )
|
Q 对象可以使用& 和| 操作符组合起来。当一个操作符在两个Q 对象上使用时,它产生一个新的Q 对象。
1
|
bookList = Book.objects. filter (Q(authors__name = "yuan" )|Q(authors__name = "egon" ))
|
等同于下面的SQL WHERE 子句:
1
|
WHERE name = "yuan" OR name = "egon"
|
你可以组合& 和| 操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询:
1
|
bookList = Book.objects. filter (Q(authors__name = "yuan" ) & ~Q(publishDate__year = 2017 )).values_list( "title" )
|
查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。例如:
1
2
3
|
bookList = Book.objects. filter (Q(publishDate__year = 2016 ) | Q(publishDate__year = 2017 ),
title__icontains = "python"
)
|
转载于:https://www.cnblogs.com/chenxi67/p/9856968.html
Django模型层的多表操作(2)相关推荐
- Django基础五之Django模型层(二)多表操作
Django基础五之Django模型层(二)多表操作 一 创建模型 表和表之间的关系 一对一.多对一.多对多 # 作者表 比较常用的信息放在这个表中 class Author(models.Model ...
- python代码函数字符查询宝典书籍_Django基础五之django模型层(一)单表操作
二 单表操作 一.创建表 创建模型 创建名为book的app,在book下的models.py中创建模型: from django.db importmodels#Create your models ...
- day55 django 模型层,orm连表操作
设计表 django之orm详解: https://www.cnblogs.com/komorebi/p/11551089.html 在django中设计表 1.先在navicat中建好一个库 2.更 ...
- Django模型层之单表操作
MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库.ORM是"对象-关系-映射 ...
- Django框架的模型层之多表操作
目录 一 创建模型 二 表记录的增删改 一对多 多对多 三.基于对象的跨表查询 一对一查询(Author 与 AuthorDetail) 一对多查询(publish与book) 多对多查询 (Auth ...
- Django基础5.1,模型层(二)多表操作
Django5.1 创建模型 建立下列模型 # 作者表 class Author(models.Model):name=models.CharField( max_length=32)age=mode ...
- Web开发-Django模型层
Django模型层 简述 Django框架处理业务的逻辑一般如下(省略图,源于网络,侵删) 可以看到,Django自带了一套ORM机制,这也是Django框架的核心-"全面",将一 ...
- Django 模型层(models) 复杂查询详解
Django 模型层(models) 复杂查询详解 一般Django orm 和原生sql混合使用 1.测试文件 只单独测试django中的某一个py文件 不一定是tests.py 1.配置 在任意一 ...
- Django–模型层orm查询
文章目录 Django–模型层orm查询 一.单表查询(增.删.改.查) 基本查询 下划线查询 二.外键字段(增.删.改.查) 一对多 多对多 三.多表查询 多表查询的方式 正反向的概念 基于对象的跨 ...
最新文章
- 经常使用的npm命令
- 聊一聊 Spring 中的线程安全性
- 我的CCIE实验考试
- hdu--Number Sequence
- 央行放水点燃房价,普通家庭如何理财?
- socket与socketServer通信
- anroid 内存溢出 Bitmap OutOfMemoryError
- Gray Code(格雷码) C++多方法实现
- python基础--局部变量与全局变量
- 普通话转粤语_语音转文字评测:几款语音转文字app,你了解多少?
- C语言 gcc 动态库
- cfar matlab,雷达无线电系列(二)经典CFAR算法图文解析与实现(matlab)
- 人脸美化随笔1——研究方向总结
- 配置cfree 5 支持C++11
- LTE相关协议2——下行峰值速率计算
- 0528班宋ww:回顾刚来的那一天还历历在目,不禁感概一番
- 程序员漫学英语单词——resume
- 一招教你快速取消Mac系统开机密码的方法
- 图灵1951年报告Intelligent Machinery,A Heretical Theory中英文,公号回复“图灵1951报告”下载PDF双语典藏版
- 西门子1200 总线控制V90伺服程序模板 两种控制模式 1.基于111报文自己编写的PN通讯控制V90伺服程序
热门文章
- 如何关闭SAP Fiori的病毒扫描设
- 一个SAP顾问的回忆:我过去很胖!
- 把日志文件从Linux服务器拷贝到Windows上
- 如何使用SAP CRM中间件下载customer material数据
- 用条件运算符编写java程序,使用条件运算符的奇怪java行为。这是一个错误吗?...
- percona mysql.cnf_Percona MySQL5.6 半同步复制
- 机器狗背上枪成了杀手,已经与美澳军队合作!
- LCD也可以模拟?这款模拟器别错过了!
- 适合STM32的三大嵌入式操作系统
- windows下的库文件在linux的使用,Windows、Linux之间传输文件的几种方式