QuerySets

QuerySets: (the thing you get when you write Question.objects.all(), filter(), order_by(), etc.)

Most beginners treat QuerySets like “just a list of objects” — but they are much smarter, lazy, chainable, SQL-optimizing magic objects. Understanding them deeply will make your code 10× faster, cleaner, and more professional.

I’m going to teach this like a senior sitting next to you — slowly, with real examples from your polls app, showing exactly what happens behind the scenes, when queries are executed, how to avoid N+1 problems, how to chain safely, and the 20 most common patterns you’ll use every day.

Let’s open python manage.py shell together and play.

1. What Actually Is a QuerySet?

Python
  • It is not a list — it is a promise to run SQL later
  • It is lazy — no database hit until you force evaluation (e.g. list(qs), for loop, len(qs), qs[0], .exists(), etc.)
  • It is immutable in chain — every method like .filter() returns new QuerySet
Python

2. Forcing Evaluation (When SQL Actually Runs)

Python

Golden rule — never evaluate large QuerySets accidentally in templates or admin:

Bad:

HTML

Good:

Python

3. Chaining Methods (The Real Power)

Every chain method returns new QuerySet — you can chain forever:

Python

Common chain methods:

Method Purpose Returns new QuerySet? Executes SQL?
.all() Start point Yes No
.filter(**kwargs) WHERE conditions Yes No
.exclude(**kwargs) NOT conditions Yes No
.order_by(“field”) ORDER BY Yes No
.values(“field1”) Return dicts instead of objects Yes No
.values_list(“field”) Return flat tuples Yes No
.only(“field1”) Only fetch these columns Yes No
.defer(“big_field”) Fetch all except these Yes No
.select_related() JOIN related objects (ForeignKey) Yes No
.prefetch_related() Separate query for ManyToMany / reverse FK Yes No
.annotate() Add computed columns Yes No
.aggregate() Compute SUM, COUNT, AVG… No — returns dict Yes
.count() Fast COUNT(*) No — returns int Yes
.exists() Fast EXISTS No — returns bool Yes
.first() / .last() LIMIT 1 No — returns object Yes
.distinct() DISTINCT Yes No

4. Lookups (The Magic in filter(field__lookup=…)) – Most Used Syntax

Python

Most common lookup suffixes (memorize these 15):

  • __exact / __iexact (case-sensitive / insensitive equal)
  • __contains / __icontains
  • __startswith / __istartswith
  • __endswith / __iendswith
  • __gt / __gte / __lt / __lte
  • __in (list/tuple)
  • __range (between two values)
  • __year / __month / __day / __week / __weekday
  • __isnull / __isnotnull
  • __regex / __iregex (rare but powerful)

5. Real Example – Complex QuerySet in View

Python

→ Efficient: only needed columns, pre-joins, annotation, limited rows

6. Avoiding N+1 Queries (Most Common Performance Killer)

Bad (N+1 problem):

HTML

→ 1 query for questions + N queries for choices = slow

Good:

Python

→ 2 queries total: one for questions, one for all related choices

7. Quick Reference – QuerySet Patterns You’ll Use Every Day

Python

Your Quick Practice Task (Do This in Shell)

  1. python manage.py shell
  2. from polls.models import Question
  3. qs = Question.objects.filter(is_active=True).order_by(“-pub_date”)[:5]
  4. print(qs) → see objects
  5. list(qs) → force evaluation
  6. qs.count() → fast COUNT
  7. qs[0] → first object
  8. Try .annotate(vote_count=Sum(“choices__votes”)) → see extra attribute

Tell me what feels next:

  • Which QuerySet part is still confusing? (chaining? lookups? N+1? annotation?)
  • Want more examples for __ lookups (dates, strings, related fields)?
  • Ready to learn Q objects (OR conditions, complex filters)?
  • Or ready to finally build Forms + Voting + POST + F() increment?

You’re getting very strong with QuerySets now — this is the single most important skill after models themselves.

Keep playing in shell — you’re doing fantastic! 🚀🇮🇳

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *