10๐
A queryset will cache its data in self._result_cache
whenever the complete queryset is evaluated. This includes iterating over the queryset, calling bool()
, len()
or list()
, or pickling the queryset.
The print()
function indirectly calls repr()
on the queryset. repr()
will evaluate the queryset to include the data in the string representation, but it will not evaluate the complete queryset. Instead, it will get a slice of the queryset and use that in the representation. This prevents huge queries when all you want is a simple string representation. Since only a slice is evaluated, it will not cache the results.
When the cache is filled, every method that does not create a new queryset object will use the cache instead of making a new query. In your specific example, if you switch the print()
and len()
statement, your queryset will only hit the database once:
user = User.objects.all()
len(user) # complete queryset is evaluated
print(user._result_cache) # cache is filled
print(user) # slicing an evaluated queryset will not hit the database
print(user._result_cache)
3๐
There is an explanation for this behavior :
When you use User.objects.all(),Database is not hit.When you do not iterate through the query set, the _result_cache is always None.But when you invoke len() function.The iteration will be done through query set, the database will be hit and resulting output will also set the result_cahce for that query set.
Here is the source code for len() function of Django :
def __len__(self):
# Since __len__ is called quite frequently (for example, as part of
# list(qs), we make some effort here to be as efficient as possible
# whilst not messing up any existing iterators against the QuerySet.
if self._result_cache is None:
if self._iter:
self._result_cache = list(self._iter)
else:
self._result_cache = list(self.iterator())
elif self._iter:
self._result_cache.extend(self._iter)
return len(self._result_cache)
Hope this clarifies all your questions. Thanks.
- [Django]-Django data migration โ class variable unavailable via get_model()
- [Django]-How to include "None" in lte/gte comparisons?
- [Django]-Opening a new browser tab invalidates Django's CSRF token, preventing form submission
- [Django]-Django / MySQL: How to do Autonomous Transactions (commit only sub-set of queries)?