一.基于对象的跨表的查询------类似于子查询
正向查询和反向查询:
比方说是出版社表和书籍表,有可能我知道这本书的名字,但是不知道出版社是哪一个,有可能知道这个出版社,但是我想知道这个出版社出版过那些书,这就是正向查询和反向查询,怎么区分正向和反向呢,这个要看我们外键字段定义在那张表(类)里面,上篇博文我们的book表中的publish外键到出版社这个表,我们从book表去查询publish表中的数据就是正向,从publish表去查询book表中的数据就是反向查询。
- 一对一
# 正向查询
# 查询张胜男的电话
obj = models.Author.objects.filter(name='张胜男').first()
print(obj.authorDetail) #北京沙河
print(obj.authorDetail.telephone) #北京沙河
#正向查询 obj.authorDetail 对象.属性
#反向查询
#查询2222电话号是谁的
obj= models.AuthorDetail.objects.get(telephone='2222')
print(obj.author.name)
#反向查询 obj.author 对象.表名小写
- 一对多
# 查询金瓶梅这本书出版社是那个
# 正向查询
obj = models.Book.objects.get(title='金瓶梅')
print(obj.publishs.name) #光学出版社
print(obj.publishs) #光学出版社 这里也打印是因为我们表中有__str__这个方法
# 正向查询:obj.publishs 对象.属性
# 反向查询
# 光学出版社出版过那些书
obj= models.Publish.objects.get(name='光学出版社')
print(obj.book_set.all()) #book_set:多对多的关系django认为会是多条 obj.book_set:类似于一个控制器在调用all方法取所有的数据
# 反向查询:obj.book_set.all() 对象.表名小写_set
这里需要注意一下:如果表中的外键字段中有参数related_name='xx' 这里做反向查询的时候直接使用obj.xx.all()不再是小写的表名 正向不会影响
- 多对多
# 金瓶梅这本书是谁写的
# 正向查询
obj = models.Book.objects.get(title='金瓶梅')
print(obj.authors.all())
#正向查询:obj.authors 对象.属性
#反向查询
# 张胜男写了那些书
obj = models.Author.objects.get(name='张胜男')
print(obj.book_set.all())
#反向查询:obj.book_set 对象.表名小写_set
二.基于双下划线的跨表查询------连表 join
一对一:
# 查询张胜男的电话
# 方式一:
# 正向查询
obj = models.Author.objects.filter(name='张胜男').values('authorDetail__telephone')
print(obj) #<QuerySet [{'authorDetail__telephone': '2222'}]>
# 方式二:
# 反向:
obj = models.AuthorDetail.objects.filter(author__name='张胜男').values('telephone','author__age')
print(obj) #<QuerySet [{'telephone': '2222'}]>
# 查询那个老师的电话是2222
# 正向:
obj = models.Author.objects.filter(authorDetail__telephone='2222').values('name')
print(obj) #<QuerySet [{'name': '张胜男'}]>
#反向
obj = models.AuthorDetail.objects.filter(telephone='2222').values('author__name')
print(obj) #<QuerySet [{'name': '张胜男'}]>
一对多:
# 查询金瓶梅这本书出版社是那个
# 正向:
obj = models.Book.objects.filter(title='金瓶梅').values('publishs__name')
print(obj) #<QuerySet [{'publishs__name': '光学出版社'}]>
# 反向查询:
obj= models.Publish.objects.filter(book__title='金瓶梅').values('name')
print(obj) #<QuerySet [{'name': '光学出版社'}]>
这里需要注意一下:如果表中的外键字段中有参数related_name='xx' 这里做反向查询的时候直接使用xx__title不再是小写的表名 正向不会影响
# 光学出版社出版过那些书
# 正向查询:
obj = models.Publish.objects.filter(name='光学出版社').values('book__title')
print(obj)
# 反向查询:
obj = models.Book.objects.filter(publishs__name='光学出版社').values('title')
print(obj) #<QuerySet [{'title': '金瓶梅'}]>
多对多:
# 金瓶梅这本书是谁写的
# 正向:
obj = models.Book.objects.filter(title='金瓶梅').values('authors__name')
print(obj)
# 反向查询:
obj = models.Author.objects.filter(book__title='金瓶梅').values('name')
print(obj)
# 张胜男写了那些书
# 反向:
obj = models.Author.objects.filter(name='张胜男').values('book__title')
print(obj)
#正向:
obj = models.Book.objects.filter(authors__name='张胜男').values('title')
print(obj)
三.基于双下划线的进阶查询
# 光学出版社 出版的书的名称以及作者的名字
obj = models.Book.objects.filter(publishs__name='光学出版社').values('authors__name','title')
print(obj)
obj = models.Publish.objects.filter(name='光学出版社').values('book__title','book__authors__name')
print(obj)
obj = models.Author.objects.filter(book__publishs__name='光学出版社').values('book__title','name')
print(obj)
# 手机号以1开头的作者出版过的所有书籍名称以及出版社名称
obj = models.AuthorDetail.objects.filter(telephone__startswith='1').values(
'author__book__title','author__book__publishs__name')
print(obj)
obj= models.Author.objects.filter(authorDetail__telephone__startswith='1').values(
'book__title','book__publishs__name')
print(obj)
obj = models.Publish.objects.filter(book__authors__authorDetail__telephone__startswith='1').values(
'book__title','name'
)
print(obj)
obj = models.Book.objects.filter(authors__authorDetail__telephone__startswith='1').values(
'title','publishs__name'
)
print(obj)
四.聚合查询
from django.db.models import Avg,Max,Min,Sum,Count
obj = models.Book.objects.all().aggregate(a=Avg('price')) #a:起别名 Avg:平均值
obj = models.Book.objects.all().aggregate(a=Max('price')) #Max:最大值
obj = models.Book.objects.all().aggregate(a=Min('price')) #Min: 最小值
obj = models.Book.objects.all().aggregate(a=Sum('price')) #Sum: 价格加在一起
obj = models.Book.objects.all().aggregate(a=Count('price')) #Sum: 总数据
print(obj) #{'a': } 返回一个字典 结束orm语句