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語句爲:python
[{'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
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'}]數據庫
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語句爲:django
[{'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()fetch
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'}]code
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'}]對象