Django之models模型层2
一、
1、案例
# 1.查询曹雪芹的手机号和作者姓名 res = models.Author.objects.filter(name='曹雪芹').values('author_detail__phone', 'name') print(res) # 使用上述的正反向查询也能,如 # res = models.AuthorDetail.objects.filter(author__name='曹雪芹').values('phone', 'author__name') # print(res) # 2、查询书籍主键为1的出版社名称和书的名称 res = models.Book.objects.filter(pk=1).values('title', 'publish__name') print(res) # <QuerySet [{'title': '平凡的世界', 'publish__name': '北京出版社'}]> # res = models.Publish.objects.filter(book__pk=1).values('name', 'book__title') # 3、 查询书籍主键为1的作者姓名 res = models.Book.objects.filter(pk=1).values('authors__name') print(res) # res = models.Author.objects.filter(book__pk=1).values('name') # print(res) # 4、查询书籍主键为1的作者手机号 # book --->(正向) author --->(正向) author_detail # 正向查询使用的是外键去跳表,比如书和作者的对应关系需要跳到authors中,主键为1的书对应的作者id为2。 res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone') print(res) # 反向查询 res = models.Author.objects.filter(book__id=1).values('name', 'author_detail__phone') print(res)
二、
1、相关基础
sum max min avg count # sql: select sum(price) from table group by ''; # 求书籍表中得书的平均价格 select avg(price) from book; from django.db.models import Max, Min, Sum, Avg, Count # 以后在导模块的时候,只要是跟数据库相关的一般都在 django.db django.db.models from django.db.models import Max, Min, Sum, Avg, Count
2、查询案例(书籍表中的平均价格、总价格等)
res = models.Book.objects.aggregate(Avg('price')) res = models.Book.objects.aggregate(Max('price'), Min('price'), Sum('price'), Avg('price'), Count('id')) print(res)
三、
1、分组查询案例
注意:annotate分组默认是以models后面的表的主键进行分组,指定字段.values(‘字段’).annotate
# 1.统计每一本书的作者个数 # book ---》 正向查询 ----》 author res = models.Book.objects.annotate(author_num=Count('authors__id')).values('author_num', 'title') # annotate以models后的表Book id进行分组,再用count函数统计作者的数量,author_num为别名。 print(res) # <QuerySet [{'title': '平凡的世界', 'author_num': 1}, {'title': '三国演义', 'author_num': 1}, {'title': '西游记', 'author_num': 2}]> # 2、统计每个出版社卖的最便宜的书的价格 res = models.Publish.objects.annotate(min_price=Min('book__price')).values('min_price', 'name') print(res) # 3、统计不止一个作者的图书 # 先按照图书进行分组,求出每个图书的作者个数,包括个数为0或者1的等,再次过滤出大于1的 res = models.Book.objects.annotate(author_num=Count('authors__pk')).filter(author_num__gt=1).values('author_num', 'title', 'id') print(res) # <QuerySet [{'title': '西游记', 'id': 2, 'author_num': 2}]> # 4、查询每个作者出的书的总价格 res = models.Author.objects.annotate(total_price=Sum('book__price')).values('total_price', 'name') print(res)
注意:
在mysql中 annotate分组只能查询到分组依据,需要取消严格模式中的‘ONLY_FULL_GROUP_BY’
这个模式要求在执行分组查询时,只有在 GROUP BY
子句中出现的列才能出现在查询的 SELECT
列表中,而不能出现在聚合函数之外。这是为了确保查询结果的一致性和可预测性。
四、
1、F 查询:
F
查询是用于在查询中引用模型的字段值,从而可以在查询中进行字段之间的比较和操作。它可以用于更新字段的值或者用于查询条件。主要用途包括:
- 在查询中比较两个字段的值。
- 在查询中进行数值运算,例如对某个字段的值进行加减操作。
- 在更新操作中使用数据库的原子操作,避免数据竞争。
2、案例
# 查询卖出数大于库存数的书籍 # sql: select * from table where maichu > kucun; from django.db.models import F from django.db.models.functions import Concat from django.db.models import Value # 1. 查询卖出数大于库存数的书籍 res = models.Book.objects.filter(maichu__gt=F('kucun')).all() print(res[0].title) # 2.将所有书籍的价格提升500块 # sql: update book set price = price+500 ; res = models.Book.objects.update(price=F('price')+500) # 3.将所有书的名称后面加上爆款两个字 # 如果是更新的字符串不能够这么来写,专业的语法来写 res = models.Book.objects.update(title=Concat(F('title'), Value('爆款')))
3、Q 查询:
Q
查询是用于构建复杂查询逻辑的对象,它可以将多个查询条件组合成更复杂的逻辑表达式,包括 AND、OR、NOT 等。使用 Q
查询可以轻松地构建出逻辑复杂且可读性强的查询条件。
波浪线 ~
用作逻辑非(NOT)运算符
from django.db.models import Q # 1.查询卖出数大于100或者价格小于600的书籍 # select *from table where maichu>100 or price < 600; # res = models.Book.objects.filter(maichu__gt=100, price__lt=600).all() # and关系 # res = models.Book.objects.filter(Q(maichu__gt=100), Q(price__lt=600)).all() # and关系 <QuerySet []> # res = models.Book.objects.filter(Q(maichu__gt=100)| Q(price__lt=600)).all() # OR关系 <QuerySet []> # res = models.Book.objects.filter(~Q(maichu__gt=100)| Q(price__lt=600)).all() # OR关系 <QuerySet []> # res = models.Book.objects.filter(~Q(maichu__gt=100)| ~Q(price__lt=600)).all() # OR关系 <QuerySet []> # res = models.Book.objects.filter(~(Q(maichu__gt=100)| Q(price__lt=600))).all() # OR关系 <QuerySet []> # print(res) # Q的高阶用法 q = Q() q.connector = 'or' # param = requests.GET.get("param") q.children.append(("maichu__gt", 600)) # q.children.append((param +"__gt", 600)) q.children.append(("price__lt", 100)) res = models.Book.objects.filter(q) print(res)
1、Django中如何开启事务
# 作用:保证安全,保证多个SQL语句要么同时执行成名, 要么同时失败 from django.db import transaction try: with transaction.atomic(): # sql1 # sql2 ... models.Book.objects.filter(maichu__gt=100, price__lt=600).update() models.Book.objects.filter(maichu__gt=100, price__lt=600).create() except Exception as e: print(e) transaction.rollback() '''BBS作业里面就可以使用事务'''