Fewer Queries
Part of the Models and the Admin section of Coddy's Django journey. Lesson 19 of 23.
The home page prints each book's author, and that has a cost: one query fetches the books, then {{ book.author.name }} runs one more query per book. Ten books, eleven queries; a thousand books, a thousand and one. This is the N+1 problem, a common reason a Django page is slow.
select_related() fixes it: the ORM fetches the related row in the same query, with a SQL JOIN. A page of loans that prints each loan's book title would ask for:
loans = Loan.objects.select_related("book")You give it the name of the ForeignKey field, the one you read as loan.book, and it still chains with filter() and order_by(). It follows ForeignKeys forward only; the way back and many-to-many fields take prefetch_related(), met in the Authors project. The page looks the same afterwards, with fewer queries.
Challenge
MediumThe home page and the search page both show each book's author. Make each fetch the authors together with the books, so the number of queries stays the same however many books there are:
- the
homeview - the
searchview
Press Run: the pages look the same. The checks count the queries.
Try it yourself
from django.shortcuts import get_object_or_404, render
from .models import Book
def home(request):
books = Book.objects.all()
return render(request, "books/home.html", {"books": books})
def book_detail(request, pk):
book = get_object_or_404(Book, pk=pk)
return render(request, "books/book_detail.html", {"book": book})
def search(request):
q = request.GET.get("q", "")
books = Book.objects.filter(title__icontains=q)
return render(request, "books/search.html", {"q": q, "books": books})
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Models and the Admin
Practice on your own: Django playground