基于对象的跨表查询(sql里的子查询)(重点)
一对多查询:
Book(有外键)--------------->Publish 属于正向查询 按book表里的字段book.publish
Book(含外键)<---------------Publish 是反向查询 按表名小写_set.all()
正向查询 例如:查python这本书的出版社的名字和邮箱
book=Book.objects.filter(title="python").first() #拿到对象, 对象.属性才可以获取值
print(book.publish.name)
print(book.publish.email)
反向查询 例如:查苹果出版社 出版的所有书籍的名字
pub_obj=Publish.objects.get(name="苹果出版社")
print(pub_obj.book_set.all()) # print(pub_obj.book_set) 出版社找书, 因为出版过很多书,所以用 _set, .all()是找出所有的书
多对多查询:
Book(有外键)--------------->Author 正向查询 按book表里的字段book.authors.all() 得到的是一个集合
Book(含外键)<---------------Publish 反向查询 按表名小写_set.all()
正向查询 例如找python作者的年龄
book=Book.objects.filter(title="python").first() #拿到python这本书
ret = book.authors.all() # 拿到与这本书关联的所有作者queryset
ret2 = book.authors.all().value("age")
print(ret2)
反向查询 例如找alex出版过的书
alex=Author.objects.filter("name"="Alex").first() #获取到alex对象 filter得到的是queryset .first()得到的是对象
print(alex.book_set.all())
一对一查询
Author--------------->AuthorDetail 正向查询 按字段 alex.ad(Author表里的字段)
Author<---------------AuthorDetail 反向查询 按表名 ad.author(表名)
正向查询 例如:查询alex的手机号
alex=Author.objects.filter("name"="alex").first()
print(alex.ad.tel)
反向查询 例如:查手机号是110的用户名
ad=AuthorDetail.objects.filter(tel=110).first()
print(ad.author.name)
-------------------------------------------------------------------------------------------------
双下划线的跨表查询(基于sql中的join实现 ) (重点)
规则:正向查询按字段 反向查询按表名的小写
不管以哪张表为基表, 写在最前面的过滤条件是不变的, 变的是过滤条件的书写方式, 就是按照上面的规则拼写
一对多
例1: 查python的出版社的名字和邮箱
以Book为基表 从Book 往Publish方向找 是正向查询
ret=Book.objects.filter(title="python").values("publish__name") #在values这开始跨表 告诉ORM的book表拼publish表
print(ret)
以Publish为基表 查出版python的出版社名字
ret=Publish.objects.filter(book__title="python").values("name")
#book__title="python" title不在基表Publish中 所以先拼表book(title字段在book中) 再反向拼表按表名小写book__title
#values("name") name是基表Publish自己的字段可以直接使用
例2: 查苹果出版社出版的所有的书的名字
以Book为基表 是正向查询
ret=Book.objects.filter(pubish__name="苹果出版社").values("title")
print(ret)
#苹果出版社不在基表Book里面,所以要先到Publish中把name="苹果出版社"的过滤出来
#title是Book基表自己的字段
以Publish为基表 反向查询
ret=Publish.objects.filter(name="苹果出版社").values("book__title"")
print(ret)
#name="苹果出版社" name在基表Pubish里面,所以直接使用name字段
#title 不在基表Publish里面, 所以要先找到Book表 (通过表名小写的方式), 再__title
多对多
例1: 查python这本书作者的名字
以Book为基表 正查按字段
ret=Book.objects.filter(title="python").values("author__age")
print(ret)
#author Book拼关联的author表 把三张表拼在一起
#title在基表Book里面
以Author为基表
ret=Author.objects.filter(book__title="python").values("age")
print(ret)
例2: 查alex出版过的书
以Book表为基表
ret=Book.objects.filter(authors__name="alex").values("title")
print(ret) # [{ "title"=python }]
以Author表为基表
ret=Author.objects.filter(name="alex").values("book__title")
print(ret) # [{ "book__title"=python }] 对比一下两种方式的查询结果
一对一
例1: 查alex的tel
以Author为基表 正向查询条件按字段
ret=Author.objects.filter(name="alex").values("ad__tel")
print(ret)
以AuthorDetail为基表
ret=AuthorDetail.objects.filter(authors__name="Alex").values("tel")
print(ret)
例2:手机号为110的作者的名字
以AuthorDetail为基表
ret=AuthorDetail.objects.filter(tel="110").values("author__name")
print(ret)
# tel在基表里面,所以直接查询.
# name不在基表里面,所以要加表名小写author__name
以Author为基表
ret=Author.objects.filter("ad__tel=110").values("name")
print(ret)
--------------------------------------------------------------------------------------------
连续跨表查询
例1: 人民出版社出版过所有书的名称以及作者的名字 (会用到Publish Book Author三张表)
以Publish为基表
ret=Publish.objects.filter(name="人民出版社").values("book__title","book__authors__name")
print(ret)
#name在基表的字段里, title和name需要用所在的表名小写连接起来再查询
#站在基表的角度跨表
以Book为基表
ret=Book.objects.filter(publish__name="人民出版社").values("title","author__name")
print(ret)
例2: 以手机号110开头的作者出版过的所有的 书的名称以及出版社名称(会用AD Author Book Publish四张表 )
以Author为基表
ret=Author.objects.filter(ad__tel__startswith=110).values("book__title","book__publish__name")
print(ret)
#没有在基表里的查询字段都需要用加引号
------------------------------------------------------------------------------------------
聚合 分组查询
from django.db.models import Avg, Sum, Max, Min, Count
聚合
例1: 查询所有书籍的平均价
ret=Book.objects.all().aggregate(priceAvg=Avg("price"))
print(ret) #{"priceAvg":123}
例2: 查有多少本书
ret=Book.objects.all().aggreagte(c=Count("nid"))
print(ret) #{"c":4}
分组 以哪个字段分组 就把哪个字段放在values()里
单表分组查询
例1: 查询Book表中每个出版社的id以及对应出版书的个数
ret=Book.objects.values("title").annotate()
#按照title分组的group by values里面是分组的字段
例2: 求每个部门的平均工资
ret=Emp.objects.values("dep").annotate(avg_salary=Avg("salary"))
# 按部门分组 求平均工资
例3: 求每个出版社 出版的书的个数
ret=Book.objects.values("pubish__id").annotate(c=Count(1))
#publish__id是Book表里的字段
print(ret)
#[{"publish_id":1, "c":2}, {"publish_id":2, "c":1}, {"publish_id":3, "c":1}]
跨表分组查询 以哪个字段分组 就把哪个字段放在values()里
例1: 查询每个出版社名称以及出版过的书的平均价格 查询什么 就以什么为基表简单点
ret=Publish.objects.values("nid").annotate(avg_price=Avg("book__price"))
# book__price拼表 按Publish表的nid分组
例2: 查询每一个作者的名字以及出版过的书的最高价 查询什么 就以什么为基表简单点
ret=Author.objects.values("name").annotate(maxPrice=Max("book__price"))
# book__price去Book表找price
例3: 查询每一个书名称以及对应的作者的个数 (Book Author表)
ret=Book.objects.values("title").annotate(Count("authors")) ?????????
例4:
ret=Publish.objects.all().annotate(avg_price=Avg("book_price")).values("name","email","avg_price")
#前面的查询结果 后面可以用????????????
例5: 查询作者数不止一个的书名以及作者的个数 (重点看看)
ret=Book.objects.annotate(c=Count("authors").filter(c__gt=1).values("title","c"))
# c 添加到了Book对象的属性中了
-------------------------------------------------------------------------
F和Q查询:
F函数查询
例1: 查询评论数大于100的书名 以哪个字段分组 就把哪个字段放在values()里
ret=Book.objects.filter(comment_count__gt=100).values("title")
例2: 评论数大于点赞数
from django.db.models. import F,Q (导入F Q函数)
ret=Book.objects.filter(comment_count__gt=F("poll_count"))
例3: 评论数大于2倍点赞数
ret=Book.objects.filter(comment_count__gt=F("poll_count")*2)
例4: 每本书的价格都在原价上加100
ret=Book.objects.all().update(price=100 + F("price"))
Q函数
例1: 查询价格大于300或者评论数大于3000的书籍
ret=Book.objects.filter(Q(price__gt=300 | Q(comment_count__gt=3000)))
原文地址:https://www.cnblogs.com/kenD/p/9867925.html