基于对象的跨表查询
#查询书籍主键为 1 的出版社名称
book_obj = models.book606.objects.filter(pk=1).first()# 书查出版社按字段
res = book_obj.publish
print(res.name)print(res.addr)# 查询作者主键为 1 的书籍
author_obj = models.author606.objects.filter(pk=1).first()# 作者查书 正向
res = author_obj.author2book.all()# <QuerySet [<book606: book606 object>]>print(res)# 查询 作者 jason 的电话号码
author_obj = models.author606.objects.filter(name="jason").first()
res = author_obj.authordetail
print(res.phone)# 什么时候加 .all 方法——当结果有多个时# 查询出版社是东方出版社的书 反向
publish_obj = models.publish606.objects.filter(pk=1).first()
res = publish_obj.book606_set.all()print(res.values("title"))# 查询聊斋的作者
book_obj = models.book606.objects.filter(pk=4).first()
res = book_obj.author606_set.all()print(res.values("name"))# 查询手机号是 110 的作者姓名
author_detail_obj = models.authordetail606.objects.filter(pk=1).first()
res = author_detail_obj.author606
print(res.name)# 当你的查询结果有多个时需要 _set.all()
联表查询(基于双下划线的跨表查询)
基于双下划线的跨表查询
# 1. 查询 jason 的手机号
res = models.author606.objects.filter(name="jason").values("authordetail__phone")print(res)# 2. 查询书籍主键为 1 的出版社名称和图书的名字
res = models.book606.objects.filter(pk=1).values("title","publish__name","publish__addr")print(res)# 3. 查询作者主键为 1 的书籍名称
res = models.author606.objects.filter(pk=1).values("author2book__title")print(res)# 查询 jason 的手机号(不使用 .author606) 反向
res = models.authordetail606.objects.filter(author606__name="jason")# 拿作者是 jason 的字段
res = models.authordetail606.objects.filter(author606__name="jason").values("phone","author606__name")print(res)# 反向2
res = models.publish606.objects.filter(book606__id=1).values("book606__title","addr")print(res)# 反向3
res = models.book606.objects.filter(author606__id=1).values("title","author606__name")print(res)# 查询书籍主键是 1 的作者的手机号
res = models.book606.objects.filter(pk=1).values("author606__authordetail__phone")print(res)# 只要掌握了正反向的概念和双下划线跨表查询就可以无限跨表
only 与 defer
select_related 与 prefetch_related
"""
orm 语句的特点
惰性查询
如果仅仅书写 orm 语句,后面没有用到查询的数据,该orm语句不会执行
"""# only 与 defer# 获取书籍表中所有书籍的名字
res = models.book606.objects.values("title")for i in res:print(i.get("title"))# 获取到的时一个数据对象 然后点title就能够拿到书名 并且没有其他字段
res = models.book606.objects.only("title")for i in res:print(i.title)# 点击 only 括号内的字段,不会走数据库print(i.price)# 点击 only 括号内以外的字段,会重新走数据库查询,而 all 不需要走# defer 和 only 刚好相反
res = models.book606.objects.defer("title")# 对象除了没有 title 对象其他字段都有for i in res:print(i.price)# select_related 与 prefetch_related 跟跨表操作有关
res = models.book606.objects.all()for i in res:# 每循环一次需要走一次数据库查询print(i.publish.name)
res = models.book606.objects.select_related("publish")# inner join# select_related 内部先联表,一次性将大表数据全部封装给查询出来的对象,这个时候对象无论什么时点击两张表的任何数据都不需要再次查询了# select_related 括号内只能放 外键字段 一对一 一对多# 多对多也不行for i in res:print(i.publish.name)
res = models.book606.objects.prefetch_related("publish")# 该方法内部是子查询,将子查询的所有结果都封装到对象中,给人的感觉像是一次性操作for i in res:print(i.publish.name)