A QuerySet represents a database query you can chain, slice, and iterate. Querysets are lazy—they hit the database only when evaluated.
Common operations
Article.objects.all()
Article.objects.filter(published=True)
Article.objects.exclude(title="Draft")
Article.objects.get(pk=5) # one row or exception
Article.objects.order_by("-created_at")[:10]
Field lookups
title__icontains="django", created_at__year=2024, author__name="Ada"—double underscore spans relationships.
Performance tip
Use select_related for ForeignKey (SQL JOIN) and prefetch_related for ManyToMany/reverse FK to avoid N+1 queries.
Important interview questions and answers
- Q: filter vs get?
A: filter returns QuerySet (0+ rows); get returns one row or raises DoesNotExist/MultipleObjectsReturned. - Q: What is N+1?
A: One query for a list plus one per row for related data—fix with select_related/prefetch_related. - Q: QuerySet caching?
A: Evaluated querysets cache results; chaining after evaluation may re-query—know when evaluation happens.
Self-check
- When does a queryset execute SQL?
- How do you fetch related author in one query?
Pitfall: Calling len() or bool() on a huge queryset still hits the database—use .exists() or .count() intentionally, and prefer slicing for previews.
Interview prep
- What is N+1?
One query for a list plus one per row for related objects—fix with select_related (FK) or prefetch_related (M2M/reverse FK).