Django模型层实现多表关系创建和多表操作( 三 )
# 一对多关系查询:查询书籍主键为1的书籍由哪个出版社出版book_obj = models.Book.objects.filter(pk=1).first()res = book_obj.publish# Publish object (1)print(res.name)# 多对多关系查询:查询数据主键为1的作者book_obj = models.Book.objects.filter(pk=1).first()res = book_obj.author# first.Author.None,说明结果有多个res_many = book_obj.author.all()# <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]># 一对一关系查询:查询作者lili的年龄author_obj = models.Author.objects.filter(name='lili').first()res = author_obj.author_detailprint(res.phone)
反向查询
反向查询如果是一对一的话是表名小写,如果是一对多或者多对多时反向查询是表明小写——set,另外如果有多个结果需要在表明小写后再加_set.all(),判断结果是否有多个的方法与正向查询相同 。当查询结果只有一个时得到的是一个模型对象,如果为多个就是QuerySet对象 。
# 一对多关系查询,查询出版社是东方出版社出版的书publish_obj = models.Publish.objects.filter(name='东方').first()res = publish_obj.book_set.all()# <QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]># 多对多关系查询,查询作者是lili写过的书author_obj = models.Author.objects.filter(name='lili').first()res = author_obj.book_set# first.Book.None,说明有多个结果res_many = author_obj.book_set.all()print(res_many)# <QuerySet [<Book: Book object (1)>]># 一对一关系查询,查询手机号是119的作者author_detail_obj = models.AuthorDetail.objects.filter(phone='119').first()res = author_detail_obj.authorprint(res.name)
联表查询
联表查询就是像MySQ里面SQL语句的联表查询一样,只不过在django的ORM里面使用基于双下划线联表查询(跨表查询) 。联表查询的可以使用一行代码查询结果,联表查询也遵循正反向关系 。
正向查询
# 一对多关系查询:查询书籍主键为1的出版社名称和书名# 首先获取书籍对象,书籍是查询publish的基表,因此获取书名直接values('names')即可,而出版社的名字是通过外键字段跳到出版社的表中农,需要通过__找到需要的字段值res = models.Book.objects.filter(pk=1).values('name', 'publish__name')# <QuerySet [{'name': '哈利波特', 'publish__name': '东方'}]># 多对多关系查询,查询书籍主键为1的作者姓名res = models.Book.objects.filter(pk=1).values('author__name')# <QuerySet [{'author__name': 'lili'}, {'author__name': 'nana'}]># 一对一关系查询,查询lili的手机号和姓名res = models.Author.objects.filter(name='lili').values('name', 'author_detail__phone').first()print(res.get('name'), res.get('author_detail__phone'))
反向查询
# 一对多关系查询:查询数据主键为1的出版社名称和书的名字res = models.Publish.objects.filter(book__id=1).values('name', 'book__name')# <QuerySet [{'name': '东方', 'book__name': '哈利波特'}]># 多对多关系查询:查询书籍主键为1的作者姓名和书名res = models.Author.objects.filter(book__id=1).values('name', 'book__name')# <QuerySet [{'name': 'lili', 'book__name': '哈利波特'}, {'name': 'nana', 'book__name': '哈利波特'}]># 一对一关系查询:查询作者id是1作者的姓名和手机号res = models.AuthorDetail.objects.filter(author__id=1).values('author__name', 'phone')# <QuerySet [{'author__name': 'lili', 'phone': '119'}]># 综合大查询:查询书籍主键是1的作者的手机号,首先获取书籍对象,书籍关联了作者表,作者表又关联了作者详情表 res = models.Book.objects.filter(pk=1).values('author__author_detail__phone')# <QuerySet [{'author__author_detail__phone': '119'}, {'author__author_detail__phone': '120'}]>
聚合查询
聚合查询通常情况下是配合分组一起使用的,聚合查询就是用一些统计工具,比如最大值,最小值,平均值等,聚合函数的导入方式from django.db.models import Max, Min, Sum, Count, Avg,如果在不分组的情况下使用聚合函数需要在aggregate()方法内使用 。
from django.db.models import Min,Max,Sum,Count,Avg# 统计书的平均价格res = models.Book.objects.aggregate(Avg('price'))print(res)# 可以将这些聚合函数同时使用res = models.Book.objects.aggregate(Max('price'),Sum('price'),Count('pk'))print(res)
分组查询
聚合函数通常和分组一起使用,分组查询的方法是annotate,默认以models.分组依据作为分组依据,即表的主键进行分组,如果annotate()方法前面出现了values()那么就会按照values中指定的值进行分组 。分组查询支持__跨表查询 。
from django.db.models import Sum, Max, Min, Avg, Count# 1.统计每本书的作者个数res = models.Book.objects.annotate(author_num=Count('author')).values('name', 'author_num')# author_num是自己定义的字段用来存储统计出来的每本书对应的作者个数,暂时存为表中的字段# 2.统计每个出版社卖的最便宜的书的价格res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name', 'min_price')# 3.统计不止一个作者的图书# 先按照图书分组,算出每本书的作者数量,再过滤出作者数量大于1的数据res = models.Book.objects.annotate(author_num=Count('author')).filter(author_num__gt=1).values('name', 'author_num')# 4.查询每个作者出版书的总价格res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name', 'sum_price')
- 千层比普通蛋糕热量低吗
- 角质层的作用
- sk2是不是越用角质层越薄
- 银渐层配蓝猫算串吗
- 空气炸锅是不是只能铺一层
- 高层阳台怎么封
- PS中的图层应该如何锁定
- 葡萄酒上面有一层白霉能喝吗
- 多层眼皮怎么贴双眼皮贴
- cpb的化妆水好用吗
