Django Filter

The filter() method narrows a QuerySet down to matching rows using field lookups, so you can express comparisons far beyond simple equality.

Filtering with filter()

filter(**kwargs) returns a new QuerySet containing only the rows that match every keyword argument passed in. When several keyword arguments are given in a single call, they are combined with SQL AND, meaning every condition must be true for a row to be included.

Example

from myapp.models import Book

# filter() returns a new QuerySet matching the conditions
published_books = Book.objects.filter(is_published=True)

# Multiple keyword arguments are combined with AND
recent_scifi = Book.objects.filter(
    genre='Sci-Fi',
    is_published=True
)

Field Lookups

A field lookup is written as field__lookup, using a double underscore to separate the field name from the comparison type. Leaving off the lookup entirely, as in filter(title='Dune'), defaults to an exact match.

  • __exact - matches the value exactly (the implicit default)
  • __gte, __lte, __gt, __lt - numeric or date comparisons
  • __contains, __icontains - substring match, icontains ignores case
  • __startswith, __endswith - match the beginning or end of a string
  • __in - matches any value inside a given list
  • __isnull - checks whether a field is NULL

Example

from myapp.models import Book

# __gte / __lte compare numbers or dates
cheap_books = Book.objects.filter(price__gte=5, price__lte=20)

# __contains / __icontains match substrings
matches = Book.objects.filter(title__icontains='django')

# __in matches against a list of values
selected = Book.objects.filter(genre__in=['Sci-Fi', 'Fantasy'])
LookupMeaning
__gte / __lteGreater than or equal to / less than or equal to
__gt / __ltStrictly greater than / strictly less than
__contains / __icontainsSubstring match, icontains ignores letter case
__inTrue if the field's value is inside a given list
__isnullTrue when the field is NULL (pass True or False)

Excluding Rows and Crossing Relationships

exclude() is the mirror image of filter(): it returns every row that does not match the given conditions. Double underscores also let a lookup follow a foreign key or related field, walking across a relationship to filter on a related model's fields.

Example

from myapp.models import Book

# exclude() returns rows that do NOT match
drafts = Book.objects.exclude(is_published=True)

# Double underscores can also cross a foreign key relationship
king_books = Book.objects.filter(author__name__icontains='king')
Note: filter(a=1, b=2) and filter(a=1).filter(b=2) both produce the same AND condition, so choose whichever reads more clearly -- chaining is especially handy when conditions are built up conditionally in Python code.

Exercise: Django Filter

What does Model.objects.filter(name='Alice') return if no rows match?