Django · 3 min read

Django QuerySets: Filter, Fetch and Avoid Extra Queries

Free Django ORM notes with a study app example, lazy QuerySets, select_related, prefetch_related and two practice questions.

A Django QuerySet represents a database query and the collection of objects it can return. Building one does not usually send the query immediately. Iterating it, converting it to a list or otherwise evaluating it fetches data.

Filter a useful subset

Suppose your app has a Note model with a title, owner and creation date. The first line builds a query; the loop evaluates it and displays matching notes.

recent = Note.objects.filter(user=request.user).order_by("-created_at")[:10]

for note in recent:
    print(note.title)

Filtering by the authenticated user also matters for privacy. Never trust a note ID alone to grant access to another learner's note.

Related objects and query count

When each note has a foreign key to an author, reading note.user.email in a loop can fetch a user repeatedly. select_related joins single-valued relationships in the main query. For a many-to-many or reverse relationship such as chapters, prefetch_related fetches related records separately and connects them in Python.

notes = (
    Note.objects
    .filter(status="published")
    .select_related("user")
    .prefetch_related("chapters")
)

for note in notes:
    print(note.title, note.user.email, len(note.chapters.all()))

The correct optimization depends on which related fields the page actually uses. Confirm with query-count tests rather than assuming every prefetch helps.

Worked check

For a learner's latest five notes, build a queryset and then inspect its results. Keep authorization in the filter:

latest = Note.objects.filter(user=request.user).order_by("-created_at")[:5]
titles = [note.title for note in latest]

Practice before checking the answer

  1. Build a queryset for the current user's notes with status published, newest first.
  2. If a list page displays each note's user.email and its chapters, which two related-object methods would you consider?
Show one possible solution
notes = (
    Note.objects
    .filter(user=request.user, status="published")
    .select_related("user")
    .prefetch_related("chapters")
    .order_by("-created_at")
)

Measure query count with representative data before and after changing a real view.

Quick review

Reference: Django QuerySet API.

Make this lesson yours

Copy the questions into a personal study note, work through the examples, and return to the parts you missed.

Try the free note editorBrowse free study tools

Keep learning