← all lessons

dailyfeed · 2026-04-27 · djangoormqueries

Field lookups

The idea

In a Django queryset, the double underscore is not just a Python-name oddity — it's a mini query DSL. field__lookup=value translates to a SQL operator:

Lookup SQL
__exact (default) =
__lt, __lte, __gt, __gte <, <=, >, >=
__in IN (...)
__isnull IS NULL / IS NOT NULL
__icontains, __istartswith LIKE '%...%', case-insensitive
__date, __year, __month DATE(col) = ..., etc.
__regex, __iregex regex match

Double underscore also crosses ForeignKey relations: Story.objects.filter(feed__user=request.user) joins through feed to filter on the related user.

How it shows up

This PR uses three different lookups in close quarters:

Q(next_check_at__isnull=True) | Q(next_check_at__lte=current)   # IS NULL / <=
Story.objects.filter(feed__user=user, published_at__date=digest_date)  # join + DATE()

The combination of join-traversal + date-truncation in one filter is what makes the ORM feel powerful — the SQL underneath is non-trivial.

Read more

Exercises

  1. Read the SQL — pick any non-trivial queryset in this repo, run it in manage.py shell, and print str(qs.query) to see the generated SQL. Note which lookups produced which clauses. Done when: you've matched at least three __lookups to their SQL counterparts in your own code.
  2. Span a relation — write a query that finds all UserFeeds belonging to staff users (user__is_staff=True). Done when: the queryset returns the right rows in shell.