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)

二、聚合查询(aggregate)

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) 

三、分组查询annotate

 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 列表中,而不能出现在聚合函数之外。这是为了确保查询结果的一致性和可预测性。

四、F与Q查询

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)

五、django中如何开启事务

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作业里面就可以使用事务'''

  

 

posted @ 2023-08-03 17:29  凡人半睁眼  阅读(8)  评论(0编辑  收藏  举报