ORM的查询

基于对象的跨表查询(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"))

# 添加到了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