Django QuerySet
A QuerySet is the collection of database rows Django gives you back when you ask a model for data, and it stays lazy until you actually force it to run.
What Is a QuerySet?
Every time you call a manager method like Model.objects.all() or Model.objects.filter(), Django hands you back a QuerySet instead of a plain Python list. A QuerySet represents a collection of rows from the database, but it is really just a description of a query -- it does not contain any data until it is evaluated.
Example
from myapp.models import Book
# Get every row in the Book table as a QuerySet
all_books = Book.objects.all()
print(type(all_books))
# <class 'django.db.models.query.QuerySet'>
for book in all_books:
print(book.title)Lazy Evaluation
Building a QuerySet with all(), filter(), exclude(), or order_by() never touches the database by itself. Django waits as long as possible and only sends SQL to the database when the result is actually needed, which is why this behavior is called lazy evaluation.
- Iterating over the QuerySet in a for loop
- Calling list(), len(), or bool() on it
- Slicing it with a step, such as queryset[0:10:2]
- Printing it in the shell, which calls repr()
Example
# Building a queryset does NOT hit the database yet
queryset = Book.objects.all()
queryset = queryset.filter(is_published=True)
queryset = queryset.order_by('-published_date')
# The SQL only runs once the queryset is evaluated,
# for example by looping over it or calling list()
recent_books = list(queryset) # database hit happens hereChaining and Caching
Methods such as filter(), exclude(), and order_by() each return a brand new QuerySet, so calls can be chained together to build up a query step by step. Once a QuerySet has been evaluated, Django caches the results on that QuerySet instance, so reusing the same variable avoids repeating the query.
Example
books = Book.objects.filter(is_published=True)
print(len(books)) # evaluates the queryset once, result is cached
for book in books: # reuses the cached result, no new query
print(book.title)
print(books.count()) # count() runs its own SQL COUNT queryExercise: Django QuerySet
What does Model.objects.all() return?