zoukankan      html  css  js  c++  java
  • 第五章、Django之多表查询进阶与事务

    [TOC]

    第五章、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会将括号内的字段排除之外将其他字段对应的值 直接封装到返回给你的对象中  点该其他字段 不需要再走数据库
        一旦你点了括号内的字段  就会频繁的去走数据库查询
        """
    

    连表操作和子查询

    
        select_related 连表操作
        # 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语句 同属于一个事务
    # 缩进出来之后自动结束
    
    #-------------------------------------------------------------------------------
    from django.db import transaction
    from rest_framework.views import APIView
    
    
    class OrderAPIView(APIView):
        def post(self,request):
            ....
            with transation.atomic():   # 开启事务,当with语句执行完成以后,自动提交事务
                pass  # 数据库操作
    

    ##六、自定义char字段 class MyCharField(models.Field): def db_type(self,connection): return 'char(%s)'%self.max_length


    ##七、ORM常用字段

    AutoField
    
    int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。
    
    IntegerField
    
    一个整数类型,范围在 -2147483648 to 2147483647。
    
    CharField
    
    字符类型,必须提供max_length参数, max_length表示字符长度。
    
    DateField
    
    日期字段,日期格式  YYYY-MM-DD,相当于Python中的datetime.date()实例。
    
    DateTimeField
    
    日期时间字段,格式 YYYY-MM-DD HH:MM:ss[.uuuuuu],相当于Python中的datetime.datetime()实例
    
    
  • 相关阅读:
    动态显隐jgGrid的列,改变列名
    从数据库获取bit类型判断的时候要注意大小写
    jqGrid自定义列的用法
    ERP中Ajax的使用
    给DataGrid或Repeater加载树状结构
    jqGrid显示树形结构
    使用json异步获取数据提交表单
    封装jQuery图表插件
    java 多线程 day10 获取线程的返回值 CallableAndFuture
    java 多线程 day09 线程池
  • 原文地址:https://www.cnblogs.com/demiao/p/11739069.html
Copyright © 2011-2022 走看看