0

Knowing that QuerySets are lazy, and a db query is made only when we try to access the queryset, I noticed that a db query is not made even if we iteratively try to access queryset object attributes (however, a query is made when we try to access the object itself). So a sample example for demonstration purposes.

from django.db import connection, reset_queries

reset_queries()
tests=Test.objects.using('db').filter(is_test=True)
print(len(connection.queries)) # returns 0
for obj in tests:
    print(obj.id)
    print(obj.is_test)
print(len(connection.queries)) # returns 0 again

The attributes are correctly printed, but how can they if it shows that a no query was made? Again if we do print(obj) instead, a query will be made. Any explanation is appreciated.

Edit: This problem arises when we try to query from a nondefault database, which I guess somewhat explains the issue.

Karen
  • 401
  • 7
  • 15

1 Answers1

1

In your example, it hits the database only once, at:

for obj in tests:
    ...

Is where the QuerySet is evaluated. From that point forward when accessing objects you are not querying the database, but rather using the QuerySet fetched data.

Niko
  • 3,012
  • 2
  • 8
  • 14
  • your answer sounds quite logical and that is what I would expect, however `print(len(connection.queries))` still returns 0, which comes down to my question. – Karen Feb 07 '23 at 10:43
  • You question is why it does not hit the database when trying to access the QS, which I answered (It does). In any case, I just tested `len(connection.queries)` before and after the evaluation and it returns 0 and 1 which is expected. – Niko Feb 07 '23 at 11:18
  • The problem was that I tried to query a non-default db with using(), in that case `print(len(connection.queries))` returns 0 after the query, otherwise, you are right, it returns 1. – Karen Feb 07 '23 at 12:15