• ORM进阶操作


    一、聚合查询:aggregate(*args, **kwargs)

    1. aggregate()QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。
      # 计算所有图书的平均价格
      from django.db.models import Avg
      Book.objects.all().aggregate(Avg('price'))
          # {'price__avg': 34.35}
      # 键的名称是按照字段和聚合函数的名称自动生成出来的。
      # 你也可以为聚合值指定一个名称,并向聚合子句提供它。
      Book.objects.aggregate(average_price=Avg('price'))
    2. 如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:

      from django.db.models import Avg, Max, Min
      Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
      # {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}

    二、分组查询:annotate() 

    1. 为调用的QuerySet中每一个对象都生成一个独立的统计值(统计方法用聚合函数)。

        a、统计每一本书的作者个数

    bookList=Book.objects.annotate(authorsNum=Count('authors'))
    for book_obj in bookList:
        print(book_obj.title,book_obj.authorsNum)

        annotate的返回值是querySet,如果不想遍历对象,可以用上valuelist:

    queryResult= Publish.objects.annotate(MinPrice=Min("book__price")).values_list("name","MinPrice")
    print(queryResult)

    三、select_related()

    1. select_related主要针一对一和多对一关系进行优化。
    2. select_related使用SQL的JOIN语句进行优化,它会自动查询出与之关联的表里的字段,一起做为查询结果,
    3. select_related不传任何参数的时候,默认会查询所有的关联对象,且会递归INNER JOIN所有的非空外键!!!
    4. select_related提供了关键字参数depth,默认为0,即递归直到最后一个对象没有非空外键为止。depth为1时只递归一级外键,以此类推。如果要访问指定深度外的字段,Django会再次进行SQL查询。
    5. 也接受无参数的调用,Django会尽可能深的递归查询所有的字段。但注意有Django递归的限制和性能的浪费。
    6. Django >= 1.7,链式调用的select_related相当于使用可变长参数。Django < 1.7,链式调用会导致前边的select_related失效,只保留最后一个

    四、prefetch_related()

    1. 对于多对多字段(ManyToManyField)和一对多字段,可以使用prefetch_related()来进行优化。
    2. prefetch_related()和select_related()的设计目的很相似,都是为了减少SQL查询的数量,但prefetch_related()的解决方法是通过分别获取各个表的内容,然后用Python处理他们之间的关系来进行优化。
    3. 可以通过传入None来清空之前的prefetch_related。

    五、extra

    1. 有些情况下,Django的查询语法难以简单的表达复杂的 WHERE 子句,对于这种情况, Django 提供了 extra() QuerySet修改机制 ,它能在 QuerySet生成的SQL从句中注入新子句
    2. extra可以指定一个或多个 参数,例如 selectwhere or tables这些参数都不是必须的,但是你至少要使用一个!要注意这些额外的方式对不同的数据库引擎可能存在移植性问题.(因为你在显式的书写SQL语句),除非万不得已,否则尽量避免这样做
      • 参数之select:                                                                                                                                                                                                                                                                                     select 参数可以让你在 SELECT 从句中添加其他字段信息,它应该是一个字典,存放着属性名到 SQL 从句的映射。

        queryResult=models.Article
                   .objects.extra(select={'is_recent': "create_time > '2017-09-05'"})

        结果集中每个 Entry 对象都有一个额外的属性is_recent, 它是一个布尔值,表示 Article对象的create_time 是否晚于2017-09-05.

      • 参数之where / tables:

        您可以使用where定义显式SQL WHERE子句 - 也许执行非显式连接。您可以使用tables手动将表添加到SQL FROM子句。

        wheretables都接受字符串列表。所有where参数均为“与”任何其他搜索条件。

        举例来讲:

        queryResult=models.Article
                   .objects.extra(where=['nid in (1,3) OR title like "py%" ','nid>2'])

    六、bulk_create()

    1. 整体插入:

      创建对象时,我们看可以通过使用bulk_create()来批量增加记录。例如:

      Entry.objects.bulk_create([
          Entry(headline="Python 3.0 Released"),
          Entry(headline="Python 3.1 Planned")
      ])

    七、defer

      有时候一个实体有过多的字段,取实体或者实体列表的时候,占用了多大的内存,而你却不需要取出全部的字段,比如博客的正文内容,你不需要立即检索数据库,这时defer就是你需要的东西。defer函数与前面讲的values有区别的,前者返回的是ValuesQuerySet,而defer返回的是QuerySet对象,这意味着,使用了defer后,你还可以结合QuerySet其他的函数,让整个语句结合更多的条件;

    八、only

      only和defer是同一类的东西,可以理解为defer的相反函数。比如Person实体里有三个字段:name age birthday,下面这两条语句是等价的:

      1)Person.objects.defer("age", "biography")

      2)Person.objects.only("name")

  • 相关阅读:
    后台http请求参数为json 【转】
    【转】java获取当前年、月、日 、小时 、分钟、 秒、 毫秒
    java 增强for循环对于空集和null的判断
    jquery中对地址中的中文进行encodeURI编码
    System.arraycopy() 数组复制方法
    增强for循环的简单总结
    【转载】oracle中decode函数用法
    【转载】用jquery给select option 赋值
    【转载】execute、executeUpdate、executeQuery三者的区别(及返回值)
    小程序table正确姿势
  • 原文地址:https://www.cnblogs.com/value-code/p/8535349.html
Copyright © 2020-2023  润新知