JB2
JB2

Reputation: 1607

count() on filter chains in Django

When chaining filters in Django, what is the most efficient way of counting the resulting records from an individual filter? Without running the filter twice that is.

i.e.

 results = my_model.objects.all() 
 for filter in my_filters:
      results = results.filter(filter.get_filter_string())
      individual_num_records_affected = my_model.objects.filter(filter.get_filter_string())

Upvotes: 0

Views: 483

Answers (1)

Rahul Gupta
Rahul Gupta

Reputation: 47866

Since you just need the number of results at each step, its more efficient to use .count() on the querysets.

From the querysets documentation:

Note: If you only need to determine the number of records in the set (and don’t need the actual objects), it’s much more efficient to handle a count at the database level using SQL’s SELECT COUNT(*). Django provides a count() method for precisely this reason.

You should not use .len() as it will load all of the record into Python objects and calls len() on the result which you don't need. You just need the number of records and .count() would be the better option.

Also, remember that querysets are evaluated lazy.

Internally, a QuerySet can be constructed, filtered, sliced, and generally passed around without actually hitting the database. No database activity actually occurs until you do something to evaluate the queryset.

So, until you try to use the results of the queryset, the queryset will not be evaluated i.e. no database hit will occur.

The statement results = results.filter(filter.get_filter_string()) will not hit the database until you try to use the results. You can do .filter() on a queryset multiple times but until you don't use it, there would be no database hit.

Upvotes: 3

Related Questions