django orm 基于双下划线的跨表查询


一..基于双下划线的跨表查询(join实现)

key:正向查询按字段,反向查询按表明小写

1.一对多跨表查询

1     查询在跨表中可以有两种方式,正向查询就是关键字段在你要搜索的表,没有关键字段就是反向查询
2     跨表查询的显著特点是__双下划线,这道题中在你要找到name,但是Book中没有,通过正向查询关键字段+__来
3     跨表找到name
4     ret=Book.objects.filter(title="python").values("publish__name")
5         # print(ret)
6     ret=Publish.objects.filter(book__title="python").values("name")
7     print(ret)   <QuerySet [{'name': '云南出版社'}]>
一对多
1     2 查询小瑞出版社出版的所有的书籍的名称
2     这道题中反向解析在出版社开始找,但是条件没有'小瑞',跨表寻找条件,
3     在filter条件先通过反向查询表名小写__+条件找到
4     ret=Book.objects.filter(publish__name="小瑞").values("title")
5     print(ret)
6     ret=Publish.objects.filter(name="小瑞").values("book__title")
7     print(ret)<QuerySet [{'book__title': 'linux'}, {'book__title': 'css'}]>
一对多反向跨表

2.多对多

1     3 查询python这本书籍的作者的年龄
2     在多对多的环境下,和一对多查询一样,是因为django是在太过强大,通过字段和表名小写
3     将多对多关系的三张表统统间接在一起,各取所需,
4     ret=Book.objects.filter(title="linux").values("authors__age")
5     print(ret)<QuerySet [{'authors__age': 18}, {'authors__age': 25}]>
6     ret=Author.objects.filter(book__title="linux").values("age")
7     print(ret)
多对多
1    4 查询alex出版过的所有的书籍名称
2     ret=Author.objects.filter(name="alex").values("book__title")
3     print(ret)<QuerySet [{'book__title': 'python5'}, {'book__title': 'linux'}, {'book__title': 'css'}]>
4     ret=Book.objects.filter(authors__name="alex").values("title")
5     print(ret)
多对多反向

3.一对一

 1     5 查询alex的手机号
 2     ret=Author.objects.filter(name="alex").values("ad__tel")
 3     print(ret)<QuerySet [{'ad__tel': 123}]>
 4     ret=AuthorDetail.objects.filter(author__name="alex").values("tel")
 5     print(ret)
 6     6 查询手机号为110的作者的名字
 7     ret=AuthorDetail.objects.filter(tel="234").values("author__name")
 8     print(ret)<QuerySet [{'author__name': 'egon'}]>
 9     ret=Author.objects.filter(ad__tel="234").values("name")
10     print(ret)
一对一

聪明的你不难发现只要掌握了查询方式key,都是一样的

4.多个表单连续查询

1   1.查询小瑞出版社出版过的所有书籍的名字以及作者的姓名
2     这里可以通过表之间的关系逐步连成一张大表查询,注意的是连接时
3     是正向还是反向查询
4     ret=Publish.objects.filter(name="小瑞").values("book__title","book__authors__name")
5     print(ret)<QuerySet [{'book__title': 'linux', 'book__authors__name': 'alex'}, {'book__title': 'css', 'book__authors__name': 'alex'}, {'book__title': 'linux', 'book__authors__name': 'egon'}, {'book__title': 'css', 'book__authors__name': 'egon'}]>
6     ret=Author.objects.filter(book__publish__name="小瑞").values("name","book__title")
7     print(ret)
多次跨表查询

 

二>

聚合,分组

聚合与分组的区别是,聚合显示的是 aggregate 后面的结果,如

而分组后的结果往往是以all() 分组的话 ,前面不写values().如

一个个queryset对象列表,,需要values 来取出接轨

要是在values为条件分组的话,显示的是values()里面的条件和annotate后面的函数 组成键值对

要是在条件的后面写上了values(),按照具体要求分组,则是会是按你的要求分组

 

1.聚合

 1     #聚合
 2     #查询所有作者的平均年龄
 3     #聚合分组前一定要引入模块,才会有效
 4     from django.db.models import Avg,Max,Sum,Min,Count
 5     # 查询坐着的平均年龄
 6     # ret=Author.objects.aggregate(Avg("age"))
 7     # print(ret){'age__avg': 21.6667}
 8     # # 查询所有书籍的个数
 9     # ret=Book.objects.aggregate(c=Count("title"))
10     # print(ret) {'c': 4}
聚合

2.分组

 

1  单表分组查询
2 这里的结果就是一个由title 与 c 组成的键值对
3     查询书籍表每一个出版社id以及对应的书籍个数
4     ret=Book.objects.values("title").annotate(c=Count(1))
5     print(ret)<QuerySet [{'title': 'python5', 'c': 1}, {'title': 'python', 'c': 1}, {'title': 'linux', 'c': 1}, {'title': 'css', 'c': 1}]>
6     # 查询每一个部门的名称以及对应员工的平均薪水
7     ret=Author.objects.values("name").annotate(a=Avg("age"))
8     print(ret)<Que
单表分组
 1 跨表分组查询
 2     在跨表分组中,可以在函数中使用跨表,也可以在后面的values()进行取键值对的跨表,和跨表查询一样
 3     查询每一个出版社的名称以及对应的书籍平均价格
 4     ret=Publish.objects.annotate(c=Avg("book__price")).values("book__title","book__price","email")
 5     print(ret)<QuerySet [{'book__title': 'python5', 'book__price': Decimal('100.00'), 'email': '234'}, {'book__title': 'python', 'book__price': Decimal('100.00'), 'email': '234'}, {'book__title': 'linux', 'book__price': Decimal('100.00'), 'email': '123'}, {'book__title': 'css', 'book__price': Decimal('150.00'), 'email': '123'}]>
 6     查询每一个作者的名字以及出版的书籍的最高价格
 7     ret=Author.objects.values("name").annotate(c=Max("book__price"))
 8     print(ret)<QuerySet [{'name': 'alex', 'c': Decimal('150.00')}, {'name': 'egon', 'c': Decimal('150.00')}, {'name': 'zero', 'c': None}]>
 9     查询每一个书籍的名称以及对应的作者的个数
10     ret=Book.objects.values("pk").annotate(c=Count("authors"))
11     print(ret)
12     ret=Book.objects.annotate(c=Count("authors"))
13     print(ret)
14     4 查询作者数不止一个的书籍名称以及作者个数
15     ret=Author.objects.annotate(c=Count("book__title")).filter(c__gt=1).values("book__title","c")
16     print(ret)
17     ret=Book.objects.annotate(c=Count("authors__name")).filter(c__gt=1).values("title","c")
18     print(ret)<QuerySet [{'title': 'python5', 'c': 2}, {'title': 'linux', 'c': 2}, {'title': 'css', 'c': 2}]>
19     5 根据一本图书作者数量的多少对查询集 QuerySet进行排序
20     ret=Book.objects.annotate(c=Count("authors__name")).order_by("c")
21     print(ret)<QuerySet [<Book: Book object (2)>, <Book: Book object (1)>, <Book: Book object (4)>, <Book: Book object (3)>]>
22     6 统计每一本以py开头的书籍的名称以及作者个数
23     ret=Book.objects.annotate(c=Count("authors__name")).filter(title__startswith="py").values("title")
24     print(ret)
多表分组

 

3.F与Q

F是在filter中,比如说进行两个变量的比较,之类的用F函数

在这之前需要引入函数

from django.db.models import F,Q
 1     from django.db.models import F,Q
 2     # 查询评论数大于100的所有的书籍名称
 3     ret=Book.objects.filter(count_num__gt=1000).values("title")
 4     print(ret)
 5     # 查询评论数大于2倍点赞数的所有的书籍名称
 6     ret=Book.objects.filter(count_num__gt=F("poll_num"))
 7     print(ret)
 8     # 查询评论数大于2倍点赞数的所有的书籍名称
 9     Book.objects.filter(count_num__gt=F("poll_num")*2)
10     ret = Book.objects.filter(Q(price__gt=300)|~Q(comment_count__gt=3000))
11     print(ret)
F函数

Q函数则是进行条件的判断时,比如价格>100或者地址在xxx"",通过比较的函数对比出来

& 和  |或 ~非

ret = Book.objects.filter(Q(price__gt=300)|~Q(comment_count__gt=3000))
print(ret)

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM