Chapter 3: Django QuerySet – Filter

QuerySet – Filter: .filter() — the heart of almost every real QuerySet you will ever write.

Most beginners do one or two simple .filter(is_active=True) and think “okay, I know how to filter”. But .filter() is actually a very rich, very expressive mini-language with 20–30 lookup types, chaining rules, Q objects, related-field traversal, negation, and performance tricks.

Today we’re going to learn it properly, step-by-step, like pair-programming in the shell — I’ll show you exactly what SQL Django generates, when it executes, what each lookup does, common beginner traps, and the 25 most useful real-world .filter() patterns you’ll copy-paste every single day.

We’ll do almost everything live in the Django shell so you can see the results immediately.

Step 1: Open the Shell & Prepare

Bash
Python

(If your database is empty, create 5–10 questions with different categories, pub_dates, vote counts via admin or shell first — it will make examples more fun.)

Step 2: The Absolute Basic .filter() (What Everyone Starts With)

Python

Generated SQL (approximate):

SQL

Step 3: Multiple Conditions = AND (Default Behavior)

Python

→ All three conditions must be true (implicit AND)

SQL:

SQL

Step 4: The 15 Most Important Lookup Types (Memorize These)

Django calls them field lookups — the __something part.

Lookup suffix Meaning Example SQL equivalent
__exact exact match (case-sensitive) category__exact=”fun” category = ‘fun’
__iexact case-insensitive exact question_text__iexact=”best biryani?” LOWER(category) = ‘fun’
__contains contains substring (case-sensitive) question_text__contains=”Hyderabad” question_text LIKE ‘%Hyderabad%’
__icontains contains (case-insensitive) question_text__icontains=”biryani” most used string search
__startswith starts with slug__startswith=”best-“ slug LIKE ‘best-%’
__endswith ends with slug__endswith=”-2026″ slug LIKE ‘%-2026’
__gt / __gte greater / greater-or-equal vote_count__gt=10 vote_count > 10
__lt / __lte less / less-or-equal pub_date__lte=timezone.now() pub_date <= NOW()
__in in list/tuple category__in=[“fun”, “sports”] category IN (‘fun’, ‘sports’)
__range between two values pub_date__range=(start, end) pub_date BETWEEN start AND end
__year / __month date part pub_date__year=2026, __month=1 EXTRACT(YEAR FROM pub_date) = 2026
__isnull IS NULL / IS NOT NULL deleted_at__isnull=True deleted_at IS NULL
__regex / __iregex regular expression slug__regex=r’^best-.*-2026$’ slug ~ ‘^best-.*-2026$’

Step 5: Combining Lookups with AND/OR/NOT

AND (multiple kwargs)

Python

OR (using Q objects)

Python

NOT / exclude

Python

Complex example (very common in real filters)

Python

Step 6: Related Field Lookups (Traversing ForeignKey / ManyToMany)

Python

Double-underscore traversal is one of Django ORM’s most beautiful features.

Step 7: Your Quick Practice Session (Do This in Shell Right Now)

  1. Get all active questions from 2026:

    Python
  2. Get fun or sports category:

    Python
  3. Get questions with “Hyderabad” in text (case-insensitive):

    Python
  4. Get questions published in last 7 days:

    Python
  5. Get questions that have choices with votes:

    Python

Tell me what feels next:

  • Which lookup or pattern is still confusing? (__icontains vs __contains? Q objects? related lookups?)
  • Want 20 more real .filter() examples from different apps/scenarios?
  • Ready to learn .annotate() + .aggregate() in detail?
  • Or finally ready for Django Forms + Voting + POST + F()?

You’re now writing real-world filters like a Django developer — this skill alone makes your views fast and expressive.

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

You may also like...

Leave a Reply

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