1.select_related: 只能用在一对多或者是一对一的关联模型之间,不能用在多对多或者是多对一的关联模型间,比如可以提前获取文章的作者,但是不能通过作者获取作者的文章,或者是通过某篇文章获取这个文章的所有的标签。

比如,想要获取与Book表通过外键的形式相关联的Author表中的数据,示例代码如下:
from django.db import connection
from django.http import HttpResponse
from .models import Article, Book, BookOrder
def index4(request):
# 1. select_related()想要获取与Book表通过外键的形式相关联的Author表中的数据
# 可以通过select_related()将相关联的表中的数据提取到内存中,减少到数据库中的查询
books = Book.objects.select_related('author')
for book in books:
print("%s, %s" % (book.author.name, book.author.age))
print(connection.queries)
# 最后django底层可以执行一条sql语句就将所有的查询操作完成

django底层执行的sql语句为:

[{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.000'},

{'sql': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.000'},

{'sql': 'SELECT book.id, book.name, book.pages, book.price, book.rating, book.author_id, book.publisher_id, book.score, author.id, author.name, author.age, author.email FROM book INNER JOIN author ON (book.author_id = author.id)', 'time': '0.016'}]

由以上的sql语句,可以看出只进行了一次查询操作,所以这就大大提高了查询的效率了。因此如果在数据量不是太大,并且经常会使用到该表的相关联的表中的数据时,就可以采用select_related()方法首先将数据提取到内存中,以便之后在进行查找的时候可以减少向数据库中发起请求的次数。

2. 采用传统的方式进行查找,获取Book表通过外键的形式相关联的Author表中的数据,

示例代码如下:
    books = Book.objects.all()
# 采用all()方法获取每个book的信息,然后向数据库中提出查询操作每个book进行一次数据库的查询,提取出name,age字段的值
for book in books:
print("%s,%s" % (book.author.name, book.author.age))
print(connection.queries)

django底层执行的sql语句为:

[{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.000'},

{'sql': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.000'},

{'sql': 'SELECT book.id, book.name, book.pages, book.price, book.rating, book.author_id, book.publisher_id, book.score FROM book', 'time': '0.000'},

{'sql': 'SELECT author.id, author.name, author.age, author.email FROM author WHERE author.id = 5 LIMIT 21', 'time': '0.000'},

{'sql': 'SELECT author.id, author.name, author.age, author.email FROM author WHERE author.id = 1 LIMIT 21', 'time': '0.000'},

{'sql': 'SELECT author.id, author.name, author.age, author.email FROM author WHERE author.id = 4 LIMIT 21', 'time': '0.000'},

{'sql': 'SELECT author.id, author.name, author.age, author.email FROM author WHERE author.id = 3 LIMIT 21', 'time': '0.000'}]

由以上sql语句可以看出,采用传统的方式执行的sql语句较多,这会大大的降低查询的效率。所以如果数据量不是太大的情况下可以采用select_related()方法将数据提取到内存中。

3. prefetch_related(): 可以对没有多对多,多对一的关联模型执行查询操作。

比如,求每本书的订阅量。示例代码如下:
def index(request):
# 3. prefetch_related()可以对多对多,多对一的关联模型操作
# 比如,求每个书的订阅量
# 返回的books中的是包裹在QuerySet中的book对象
books = Book.objects.prefetch_related('bookorder_set')
print(type(books))
# <class 'django.db.models.query.QuerySet'>
for book in books:
print(type(book))
# <class 'front.models.Book'>, 之后就可以对返回的每一本书上的属性进行操作
# 以下我们可以提取出每本书上的所有订单信息
# 注意:如果已经使用prefetch_related()进行了相关的查找,这里就不要使用filter()或者是其他的可以返回QuerySet的任何操作了。
# book_nums = book.bookorder_set.filter(price__gte=80)
# 这里可以使用all()方法进行获取。如果对bookorder再次进行了查询就会增加n个查询语句,降低查询的效率
book_nums = book.bookorder_set.all()
for book_num in book_nums:
print("%s, %s, %s" % (book_num.book.name, book_num.price, book_num.id))
print(connection.queries)
return HttpResponse("success!")

django底层执行的sql语句为:

[{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.000'},

{'sql': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.000'},

{'sql': 'SELECT book.id, book.name, book.pages, book.price, book.rating, book.author_id, book.publisher_id, book.score FROM book', 'time': '0.000'},

{'sql': 'SELECT book_order.id, book_order.book_id, book_order.price, book_order.time FROM book_order WHERE book_order.book_id IN (1, 2, 3, 4)', 'time': '0.000'}]

总结:在多对多,多对一关联对象中执行查询操作,可以使用prefetch_related()进行相关查询,这种方式中可以大大减少执行的sql语句,并且这种方式会产生两条查询语句。同样也可以使用prefetch_related()对一对多或者是一对一的关联对象进行相关查询,同样也会在底层执行两条sql语句,如果使用select_related()进行查询的话只会执行一条查询语句。所以说如果是对一对一或者是一对多关联对象执行操作的话,建议使用select_related(); 如果是多对一或者是多对多关联模型执行操作时,就可以采用prefetch_related()

4. 采用传统的方式执行与prefetch_related()作用相同的操作,查看django底层执行的sql语句,

示例代码如下:
def index(request):
# 4. 使用传统的方法对多对多或者是多对一的关联模型表进行查询操作
books = Book.objects.all()
for book in books:
print(type(book))
# # <class 'front.models.Book'>
book_nums = book.bookorder_set.all()
for book_num in book_nums:
print(type(book_num))
# # <class 'front.models.BookOrder'>
print("%s, %s, %s" % (book_num.book.name, book_num.price, book_num.id))
print(connection.queries)
return HttpResponse("success")

django底层执行的sql语句:

[{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.000'},

{'sql': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.000'},

{'sql': 'SELECT book.id, book.name, book.pages, book.price, book.rating, book.author_id, book.publisher_id, book.score FROM book', 'time': '0.000'},

{'sql': 'SELECT book_order.id, book_order.book_id, book_order.price, book_order.time FROM book_order WHERE book_order.book_id = 1', 'time': '0.000'},

{'sql': 'SELECT book_order.id, book_order.book_id, book_order.price, book_order.time FROM book_order WHERE book_order.book_id = 2', 'time': '0.000'},

{'sql': 'SELECT book_order.id, book_order.book_id, book_order.price, book_order.time FROM book_order WHERE book_order.book_id = 3', 'time': '0.000'},

{'sql': 'SELECT book_order.id, book_order.book_id, book_order.price, book_order.time FROM book_order WHERE book_order.book_id = 4', 'time': '0.016'}]

由以上所执行的sql语句可以看出,采用传统的方式会使底层执行的sql语句的数量增大

5. 如果在某些情况下需要对预先查询的结果,再进行一些操作,可以使用Prefetch()函数,

示例代码如下:
def index5(request):
# 5.如果确实要对预先查询的结果,再进行一些操作的话,可以使用Prefetch()函数
# 可以将要进行的操作赋值给Prefetch函数中的queryset参数
prefetch = Prefetch('bookorder_set', queryset=BookOrder.objects.filter(price__gte=90))
books = Book.objects.prefetch_related(prefetch)
for book in books:
# <class 'front.models.BookOrder'>
orders = book.bookorder_set.all()
for order in orders:
print("%s, %s, %s" % (order.book.name, order.price, order.id))
print(connection.queries)
return HttpResponse("success")

django底层执行的sql语句为:

水浒传, 95.0, 2

[{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.000'},

{'sql': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.000'},

{'sql': 'SELECT book.id, book.name, book.pages, book.price, book.rating, book.author_id, book.publisher_id, book.score FROM book', 'time': '0.000'},

{'sql': 'SELECT book_order.id, book_order.book_id, book_order.price, book_order.time FROM book_order WHERE (book_order.price >= 90.0e0 AND book_order.book_id IN (1, 2, 3, 4))', 'time': '0.000'}]

84.常用的返回QuerySet对象的方法使用详解:select_related, prefetch_related的更多相关文章

  1. 82.常用的返回QuerySet对象的方法使用详解:all,select_related

    1. all: 返回这个ORM模型的QuerySet对象. articles = Article.objects.all() print(articles) 2.select_related: 查找数 ...

  2. 85.常用的返回QuerySet对象的方法使用详解:defer,only

    defer(),only(): 这两个方法都会返回一个"QuerySet"对象,并且这个"QuerySet"中装的是模型,不像values()和values_l ...

  3. 81.常用的返回QuerySet对象的方法使用详解:values和values_list

    values: 指定提取的数据库表中的字段值,如果不指定任何的字段名的话,默认情况下会提取所有的字段值.但是需要注意的是使用values返回的QuerySet对象中包括的是一个个的字典. 1.提取与A ...

  4. 79.常用的返回QuerySet对象的方法使用详解: filter, exclude,annotate

    返回新的QuerySet的常用方法: 1.filter: 将满足条件的数据提取出来,返回一个新的QuerySet 以下所使用的模型article,category,定义模型models.py文件中,示 ...

  5. 80.常用的返回QuerySet对象的方法使用详解:order_by

    order_by: 将模型生成的表按照某个字段进行排序,默认情况下,按照升序的顺序排序,如果想要按照降序的顺序排序可以在字段的前面加一个"-",加一个负号就可以进行反转. mode ...

  6. asp.net中C#对象与方法 属性详解

    C#对象与方法 一.相关概念: 1.对象:现实世界中的实体 2. 类:具有相似属性和方法的对象的集合 3.面向对象程序设计的特点:封装  继承 多态 二.类的定义与语法 1.定义类: 修饰符 类名称 ...

  7. js对象浅拷贝和深拷贝详解

    js对象浅拷贝和深拷贝详解 作者:i10630226 字体:[增加 减小] 类型:转载 时间:2016-09-05我要评论 这篇文章主要为大家详细介绍了JavaScript对象的浅拷贝和深拷贝代码,具 ...

  8. 2020你还不会Java8新特性?方法引用详解及Stream 流介绍和操作方式详解(三)

    方法引用详解 方法引用: method reference 方法引用实际上是Lambda表达式的一种语法糖 我们可以将方法引用看作是一个「函数指针」,function pointer 方法引用共分为4 ...

  9. Underscore _.template 方法使用详解

    为什么用「void 0」代替「undefined」 undefined 并不是保留词(reserved word),它只是全局对象的一个属性,在低版本 IE 中能被重写. 事实上,undefined ...

随机推荐

  1. redis的配置文件介绍

    目录 1.开头说明 2.INCLUDES 3.MODULES 4.NETWORK 5.GENERAL 6.SNAPSHOTTING 7.REPLICATION 8.SECURITY 9.CLIENTS ...

  2. Oracle SQL触发器

    一.触发器 触发器是一个数据库对象,是一个特殊的过程,当特定的时间发生时隐式地执行.比如在一个表中发生插入.更新或删除的时间,或者 CREATE.ALTER 这样的数据定义语句执行时,触发器会隐式执行 ...

  3. 《新标准C++程序设计》3.8(C++学习笔记10)

    友元 友元分为友元函数和友元类两种. 一.友元函数 在定义一个类的时候,可以把一些函数(包括全局函数和其它类的成员函数)声明为“友元”,这样那些函数就成为该类的友元函数,在友元函数内部就可以访问该类对 ...

  4. Web安全常见问题及解决方法

    关于Web安全,我们最早听到最多的就是SQL注入.例如用户在系统登录界面输入用户名和密码,提交以后,后端直接拿到数据就拼接SQL语句去查询数据库.如果在输入时进行了恶意的SQL拼装,那么最后生成的SQ ...

  5. JAXB工具

    在JDK6之后,都自带了JAXB工具,所以在jdk类库与tomcat WEBAPP类库之间,会造成冲突 https://blog.csdn.net/iteye_13776/article/detail ...

  6. JVM源码分析之自定义类加载器如何拉长YGC

    概述 本文重点讲述毕玄大师在其公众号上发的一个GC问题一个jstack/jmap等不能用的case,对于毕大师那篇文章,题目上没有提到GC的那个问题,不过进入到文章里可以看到,既然文章提到了jstac ...

  7. bfs--P1301 魔鬼之城

    *传送 求最小步数,bfs求解.因为题目要求可以走八个方向(上下左右和对角线),所以两个方位数组来找八个方向 int dirx[9]={0,0,1,1,1,0,-1,-1,-1}; int diry[ ...

  8. Hadoop家族系统学习路线

    本文主要介绍Hadoop家族产品,常用的项目包括Hadoop,Hive,Pig,HBase,Sqoop,Mahout,Zookeeper,Avro,Ambari,Chukwa,新增加的项目包括,YAR ...

  9. SQL注入类型

    本文转自:https://www.cnblogs.com/cui0x01/p/6322826.html Sql注入_类型 1.sql注入 通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询 ...

  10. LIS是什么?【通讯】

    Ⅲ最后一点,通讯. 从字面意义来看,通讯是一种沟通形式,信息交互的媒介.在LIS中,通讯主要指的是仪器通讯,也就是仪器与电脑-LIS系统的信息交互方式,也可以称为仪器接口. 在LIS中,通讯是最基础也 ...