Using len(queryset) instead of queryset.count()

len(queryset) performs the count at application level. That is much less efficient than doing queryset.count(), which does the calculation at database level and just returns the count.

Querysets are lazily evaluated - meaning the records are not read from the database until code interact with the data. Thats's why we can do queryset.all() without downloading every records from the database.

An example of something that interacts with the data is doing len(queryset). This will read all the records in the queryset: effectively downloading the database over the internet. Not particularly efficient.

On the other hand doing queryset.count() handles the calculation at the database level by executing SQL like SELECT COUNT(*) FROM table.

That means using queryset.count() makes the code quicker, and improves database performance. Plus imagine the waste in downloading 5000 records only to check the length and throw them away at the end! Having said that though, if the records will need reading after the length if checked, then len(queryset) can be valid.

If we spot this issue in your GitHub pull request we give this advice:

tasks.pyperformancemedium
def task(admin_blog_ids):
    queryset = CommentModel.objects.all()
-
    if len(queryset) > 100:
+
    if queryset.count() > 100:
        send_email_to_admin(queryset)

len(queryset) performs the count at application level. That is much less efficient than doing queryset.count(), which does the calculation at database level and just returns the count.

Read more
Protect your pull requests from over 40 types of common Django technical debts with our GitHub code review bot.

Configuring this check

Django Doctor will run this check by default. No configuration is needed but the check can be turned on/off using check code queryset-length in your pyproject.toml file.

Read more about configuring Django Doctor.