Django admin list does Count query twice

I didn’t want to create a bug directly, since I’m not sure if I’m missing something before reporting it.
With the admin setting show_full_result_count enabled, if you go to a list. Django does the count(*) query twice, both in ChangeList.get_results()

This is the relevant code, I added some extra comments.

        # Get the number of objects, with admin filters applied.
        result_count = paginator.count  # First count() query

        # Get the total number of objects, with no admin filters applied.
        if self.model_admin.show_full_result_count:
            full_result_count = self.root_queryset.count()  # Second count() query
        else:
            full_result_count = None

If there are filters applied to the list, there’s need for both count queries, but if there are not, there’s no need to do the count() again.

So this should avoid the second query if there are no filters. (Not tested)

        # Get the number of objects, with admin filters applied.
        result_count = paginator.count

        # Get the total number of objects, with no admin filters applied.
        if self.model_admin.show_full_result_count:
            if self.has_active_filters:
                full_result_count = self.root_queryset.count()
            else:
                full_result_count = result_count
        else:
            full_result_count = None

I’ll be happy to do a pull request, but before wasting the maintainers time with this I wanted to see if someone else could confirm my understanding.

2 Likes

Hmm, I’d be inclined to +1 this because a full table count could be costly :thinking:

btw you could flatten the if/else nesting to this:

if not self.model_admin.show_full_result_count:
    full_result_count = None
elif self.has_active_filters:
    full_result_count = self.root_queryset.count()
else:
    full_result_count = result_count

ps this is in the Mentorship sub-category, it’s possible folks interested in having a say aren’t watching here

I have also faced this in the past when debugging queries with django-debug-toolbar. I was puzzled for a while trying to understand why DDT would report a repeated COUNT(*) query to be performed twice, until I realized it had to do when filters were (or were not) used.

I’m +1 to having this improved!

Thanks for the responses, I have created an issue in the bug tracker and a pull request, hoping I did everything right as a first contributor.

2 Likes