• day 61 聚合查询,分组查询,F与Q查询,orm中常见的字段,查询优化,django中的orm事务操作


       聚合查询

       #聚合函数
       from django.db.models import Max,Min,Sum,Count,Avg

       关键字: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

    Employee.objects.values("dept").annotate(avg=Avg("salary").values(dept, "avg"),
    这里需要注意的是annotate分组依据就是他前面的值,
    如果前面没有特点的字段,则默认按照ID分组,
    这里有dept字段,所以按照dept字段分组。

       value里面的参数对应的是sql语句中的select要查找显示的字段,

       filter里面的参数相当于where或者having里面的筛选条件

       annotate本身表示group by的作用,前面找寻分组依据,

       内部放置显示可能用到的聚合运算式,后面跟filter来增加限制条件,最后的value来表示分组后想要查找的字段值。



    # 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
    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)) # 波浪号 表示非
    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)
    括号里左边跟orm查询语句里的字段名条件书写一模一样


    查询优化
    # only

    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会将括号内的字段对应的值 直接封装到返回给你的对象中 点该字段 不需要再走数据库
    一旦你点了不是括号内的字段 就会频繁的去走数据库查询
    """
    # defer
    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(外键字段__外键字段__外键字段...)
    """

    """
    第一个 内部自动连表 消耗的资源就在连表上 但是走数据库的次数较少

    第二个 内部不做连表 消耗的资源就在查询次数上 但是给用户的感觉跟连表操作一样

    """








    orm查询常见字段

      orm中常见字段
      AutoField(primary_key=True)
      CharField(max_length=32) varchar(32)
      IntegerField() int
      BigIntegerField() long
      DateField()
      auto_now:每次修改数据的时候 都会更新该字段
      auto_now_add:只在创建数据的时候 才会自动将创建时间添加 后续不会再自动修改了
      DecimalField()
      BooleanField(Field)
      - 布尔值类型
      该字段在存储数据的时候 你只需要传布尔值即可  
      对应到数据库中 会变成0/1
      TextField(Field)
      - 文本类型

      存大段文本
      EmailField(CharField) varchar(...)
      

      FileField(Field)
      - 字符串,路径保存在数据库,文件上传到指定目录
      - 参数:
    upload_to = "" 上传文件的保存路径
    storage = None 存储组件,默认django.core.files.storage.FileSystemStorage

      DecimalField(Field)
      - 10进制小数
      - 参数:
      max_digits,小数总长度
      decimal_places,小数位长度




    # 自定义char类型字段
    class MyCharField(models.Field):
      def __init__(self,max_length,*args,**kwargs):
        self.max_length = max_length
        super().__init__(max_length=max_length,*args,**kwargs)

      def db_type(self, connection):
        return 'char(%s)'%self.max_length


    如果你使用的是django2.X版本 你在建数据库表关系的时候
    你需要手动指定两个参数
    (你要手动告诉django 级联更新 级联删除 是否建外键约束)
    on_delete
    db_constraint

     


    django orm中的事务操作
      ACID:
      原子性
      一致性
      隔离性
      持久性


    commit
    rollback
    要么同时成功要么同时失败

    from django.db import transaction
    with transaction.atomic():
    # 在该代码块中所写的orm语句 同属于一个事务
    # 缩进出来之后自动结束

     


  • 相关阅读:
    如何制定一周工作计划
    如何评估工作offer(1)
    Iraq shoethrower inspires Web games
    数据加密技术
    数字签名技术原理
    [转载]CSS使用技巧大全
    数字签名介绍
    数字签名原理剖析
    6个有用的MySQL语句
    PGP概述及原理
  • 原文地址:https://www.cnblogs.com/wwei4332/p/11739133.html
Copyright © 2020-2023  润新知