zoukankan      html  css  js  c++  java
  • 084:QuerySet API详解prefetch_related方法

    QuerySet API详解prefetch_related方法:

    prefetch_related :这个方法和 select_related 非常的类似,就是在访问多个表中的数据的时候,减少查询的次数。这个方法是为了解决 多对一 和 多对多 的关系的查询问题。比如要获
    取标题中带有 hello 字符串的文章以及他的所有标签,示例代码如下:

    from django.db import connection
    articles = Article.objects.prefetch_related("tag_set").filter(title__contains='hello')
    print(articles.query) # 通过这条命令查看在底层的SQL语句
    for article in articles:
      print("title:",article.title)
      print(article.tag_set.all())
    
    # 通过以下代码可以看出以上代码执行的sql语句
    print(connection.queries)

    但是如果在使用 article.tag_set 的时候,如果又创建了一个新的 QuerySet 那么会把之前的 SQL 优化给破坏掉。比如以下代码:

    tags = Tag.obejcts.prefetch_related("articles")
    for tag in tags:
      articles = tag.articles.filter(title__contains='hello') #因为filter方法会重新生成一个QuerySet,因此会破坏掉之前的sql优化
    # 通过以下代码,我们可以看到在使用了filter的,他的sql查询会更多,而没有使用filter的,只有两次sql查询
    
    print(connection.queries)

    那如果确实是想要在查询的时候指定过滤条件该如何做呢,这时候我们可以使用 django.db.models.Prefetch 来实现, Prefetch 这个可以提前定义好 queryset 。示例代码如下:

    tags = Tag.objects.prefetch_related(Prefetch("articles",queryset=Article.objects.f
    ilter(title__contains='hello'))).all()
    for tag in tags:
      articles = tag.articles.all()
      for article in articles:
        print(article)
    print(connection.queries)

    因为使用了 Prefetch ,即使在查询文章的时候使用了 filter ,也只会发生两次查询操作。

    实例代码和截图:

        # books = Book.objects.all()
        # books = Book.objects.prefetch_related("bookorder_set")
        # for book in books:
        #     print("#"*30)
        #     print(book.name)
        #     orders = book.bookorder_set.all()
        #     for order in orders:
        #         print(order.id)
    
        # books = Book.objects.prefetch_related("author")
        # for book in books:
        #     print(book.author.name)
    
        # books = Book.objects.prefetch_related("bookorder_set")
        # for book in books:
        #     print(book.name)
        #     orders = book.bookorder_set.filter(price__gte=90)
        #     for order in orders:
        #         print(order.id)
    
        prefetch = Prefetch("bookorder_set", queryset=BookOrder.objects.filter(price__gte=90))
        books = Book.objects.prefetch_related(prefetch)
        for book in books:
            print("#"*30)
            print(book.name)
            orders = book.bookorder_set.all()
            for order in orders:
                print(order.id)
    
        print(connection.queries)
  • 相关阅读:
    和菜鸟一起学linux之bluetooth学习记录基础知识
    教父马云的经典语录汇总
    win32 多线程基础
    自己收集整理的微软错误代码大全(中文和英文)
    如何解决数据库中的字符型字段值中包含'0A'时,导出的文件用EXECEL打开时行数变多或者将结果导入数据库出错
    win32 TCP网络文件传输服务器端1.23
    Android窗口管理服务WindowManagerService对窗口的组织方式分析
    和菜鸟一起学linux总线驱动之DMA传输
    win 32下c语言文件传输客户端1.23
    Resolution to the record count increasing of the file exported from DB when ‘0A’ is included in it
  • 原文地址:https://www.cnblogs.com/zheng-weimin/p/10281861.html
Copyright © 2011-2022 走看看