084:QuerySet API详解prefetch_related方法
Posted zheng-weimin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)
以上是关于084:QuerySet API详解prefetch_related方法的主要内容,如果未能解决你的问题,请参考以下文章
091:QuerySet API详解-update和delete
079:Django数据库QuerySet API详解-filterexcludeannotate