Menu
CoddyTech

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. For an author's books and for many-to-many fields you need prefetch_related(), used in the Authors project. The page looks the same afterwards, with fewer queries.

challenge icon

Challenge

Medium

In books/views.py, make the QuerySets in home and search fetch each book's author in the same query. Keep the search filter.

Press Run: the pages look the same. The checks add ten books and allow two queries per page.

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})
quiz iconTest yourself

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