Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #11295: If ModelAdmin.queryset returns a filtered QS don't requ…

…ire a 2nd count call

Original patch rewritten, added tests and get_filters_params method for ChangeList class.
Thanks Alex for the report.
  • Loading branch information...
commit f07a5f0a21857204465019b4e68f914d31cb396a 1 parent e4ee3d8
@viciu viciu authored
View
29 django/contrib/admin/views/main.py
@@ -79,15 +79,23 @@ def __init__(self, request, model, list_display, list_display_links,
self.title = title % force_text(self.opts.verbose_name)
self.pk_attname = self.lookup_opts.pk.attname
- def get_filters(self, request):
- lookup_params = self.params.copy() # a dictionary of the query string
- use_distinct = False
-
+ def get_filters_params(self, params=None):
+ """
+ Returns all params except IGNORED_PARAMS
+ """
+ if not params:
+ params = self.params
+ lookup_params = params.copy() # a dictionary of the query string
# Remove all the parameters that are globally and systematically
# ignored.
for ignored in IGNORED_PARAMS:
if ignored in lookup_params:
del lookup_params[ignored]
+ return lookup_params
+
+ def get_filters(self, request):
+ lookup_params = self.get_filters_params()
+ use_distinct = False
# Normalize the types of keys
for key, value in lookup_params.items():
@@ -166,14 +174,13 @@ def get_results(self, request):
result_count = paginator.count
# Get the total number of objects, with no admin filters applied.
- # Perform a slight optimization: Check to see whether any filters were
- # given. If not, use paginator.hits to calculate the number of objects,
- # because we've already done paginator.hits and the value is cached.
- if not self.query_set.query.where:
- full_result_count = result_count
- else:
+ # Perform a slight optimization:
+ # full_result_count is equal to paginator.count if no filters
+ # were applied
+ if self.get_filters_params():
full_result_count = self.root_query_set.count()
-
+ else:
+ full_result_count = result_count
can_show_all = result_count <= self.list_max_show_all
multi_page = result_count > self.list_per_page
View
28 tests/regressiontests/admin_views/tests.py
@@ -2537,6 +2537,34 @@ def test_changelist_view(self):
else:
self.assertNotContains(response, 'Primary key = %s' % i)
+ def test_changelist_view_count_queries(self):
+ #create 2 Person objects
+ Person.objects.create(name='person1', gender=1)
+ Person.objects.create(name='person2', gender=2)
+
+ # 4 queries are expected: 1 for the session, 1 for the user,
+ # 1 for the count and 1 for the objects on the page
+ with self.assertNumQueries(4):
+ resp = self.client.get('/test_admin/admin/admin_views/person/')
+ self.assertEqual(resp.context['selection_note'], '0 of 2 selected')
+ self.assertEqual(resp.context['selection_note_all'], 'All 2 selected')
+ with self.assertNumQueries(4):
+ extra = {'q': 'not_in_name'}
+ resp = self.client.get('/test_admin/admin/admin_views/person/', extra)
+ self.assertEqual(resp.context['selection_note'], '0 of 0 selected')
+ self.assertEqual(resp.context['selection_note_all'], 'All 0 selected')
+ with self.assertNumQueries(4):
+ extra = {'q': 'person'}
+ resp = self.client.get('/test_admin/admin/admin_views/person/', extra)
+ self.assertEqual(resp.context['selection_note'], '0 of 2 selected')
+ self.assertEqual(resp.context['selection_note_all'], 'All 2 selected')
+ # here one more count(*) query will run, because filters were applied
+ with self.assertNumQueries(5):
+ extra = {'gender__exact': '1'}
+ resp = self.client.get('/test_admin/admin/admin_views/person/', extra)
+ self.assertEqual(resp.context['selection_note'], '0 of 1 selected')
+ self.assertEqual(resp.context['selection_note_all'], '1 selected')
+
def test_change_view(self):
for i in self.pks:
response = self.client.get('/test_admin/admin/admin_views/emptymodel/%s/' % i)
Please sign in to comment.
Something went wrong with that request. Please try again.