第五章、Django之多表查询
一、聚合查询
关键字:aggregate
from django.db.models import Max,Min,Count,Sum,Avg 统计所有书平均价格 res = models.Book.objects.all().aggregate(Avg('price')) res1 = models.Book.objects.all().aggregate(Max('price')) res2 = models.Book.objects.all().aggregate(Min('price')) res3 = models.Book.objects.all().aggregate(Sum('price')) res4 = models.Book.objects.all().aggregate(Count('title')) res5 = models.Book.objects.all().aggregate(Avg('price'),Max('price'),Min('price'),Sum('price'),Count('title')) print(res5)
二、分组查询
关键字:annotate
#1.统计每一本书的作者个数 res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num') print(res) #2.统计出每个出版社卖的最便宜的书的价格 res = models.Publish.objects.annotate(price_min=Min('book__price')).values('price_min') print(res)
# 3.统计不止一个作者的图书 """ 1.统计每本书对应的作者个数 2.基于上面的结果 筛选出作者个数大于1 的 """ # res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('author_num') # print(res) # 4.查询各个作者出的书的总价格 # res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('sum_price') # print(res)
三、F与Q查询
""" F与Q查询 我们之前在查询数据库的时候条件都是我们自己手写的 但是现在出现了条件是从数据库里面获取的 """
# F from django.db.models import F,Q # 1.查询出卖出数大于库存数的书籍 # res = models.Book.objects.filter(maichu__gt=F('kucun')) # print(res) # 2.将所有的书的价格 全部提高100块 # models.Book.objects.update(price=F('price') + 100) # 3.了解 尝试着将所有的书的名字后面都加上 爆款
# Q查询 # 1.查询书籍名称是python入门或者价格是544.44的书 # res = models.Book.objects.filter(title='python入门',price=544.44) # res = models.Book.objects.filter(Q(title='python入门'),Q(price=544.44)) # 逗号就是and # res = models.Book.objects.filter(Q(title='python入门')|Q(kucun=666)) # 用来Q之后 就能够支持|表示或 # res = models.Book.objects.filter(~Q(title='python入门')|Q(kucun=666)) # esc下面那个键 波浪号 表示非 # print(res) # Q查询进阶用法 用Q产生对象 然后再使用 # q = Q() # q.connector = 'or' # q.children.append(('title__icontains','p')) # # q.children.append(('kucun',666)) # res = models.Book.objects.filter(q) # print(res) """ 字符串的左边 跟你的变量名条件书写一模一样 """
四、查询优化
only与defer
# res = models.Book.objects.all() # res = models.Book.objects.values('title') # res = models.Book.objects.only('title') # for r in res: # # print(r.title) # print(r.price) """ only会将括号内的字段对应的值 直接封装到返回给你的对象中 点该字段 不需要再走数据库 一旦你点了不是括号内的字段 就会频繁的去走数据库查询 """
# res = models.Book.objects.defer('title') # defer和only互为反关系 # for r in res: # print(r.title) """ defer会将括号内的字段排除之外将其他字段对应的值 直接封装到返回给你的对象中 点该其他字段 不需要再走数据库 一旦你点了括号内的字段 就会频繁的去走数据库查询 """
五、连表操作和子查询
连表操作
# res = models.Book.objects.select_related('publish') # res1 = models.Author.objects.select_related('author_detail') # # res = models.Book.objects.all() # for r in res1: # print(r.author_detail) # print(r.author_detail.phone) # print(r.author_detail.addr) """ select_related 会自动帮你做连表操作 然后将连表之后的数据全部查询出来封装给对象 select_related括号内只能放外键字段 并且多对多字段不能放 如果括号内外键字段所关联的表中还有外键字段 还可以继续连表 select_related(外键字段__外键字段__外键字段...) """
子查询
# prefetch_related res = models.Book.objects.prefetch_related('publish') # print(res) for r in res: print(r.publish.name) """ prefetch_related 看似连表操作 其实是类似于子查询 prefetch_related括号内只能放外键字段 并且多对多字段不能放 如果括号内外键字段所关联的表中还有外键字段 还可以继续连表 select_related(外键字段__外键字段__外键字段...) """
总结
第一个 内部自动连表 消耗的资源就在连表上 但是走数据库的次数较少 第二个 内部不做连表 消耗的资源就在查询次数上 但是给用户的感觉跟连表操作一样
六、Django开启事务
from django.db import transaction with transaction.atomic(): # 在该代码块中所写的orm语句 同属于一个事务 # 缩进出来之后自动结束