From 8f76673f344750d863ae0856040d89c9f67baa8c Mon Sep 17 00:00:00 2001 From: nmhung89 Date: Sun, 23 Oct 2016 21:55:53 +1000 Subject: [PATCH] Fixed #18729 -- Made admin changelist not use distinct() if a list_filter doesn't require it. --- django/contrib/admin/views/main.py | 9 +++++++-- tests/admin_changelist/tests.py | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py index cf392e418f9..81facb9b823 100644 --- a/django/contrib/admin/views/main.py +++ b/django/contrib/admin/views/main.py @@ -125,12 +125,17 @@ class ChangeList(object): if not isinstance(field, models.Field): field_path = field field = get_fields_from_path(self.model, field_path)[-1] + + lookup_params_count = len(lookup_params) spec = field_list_filter_class( field, request, lookup_params, self.model, self.model_admin, field_path=field_path ) - # Check if we need to use distinct() - use_distinct = use_distinct or lookup_needs_distinct(self.lookup_opts, field_path) + # field_list_filter_class removes any lookup_params it + # processes. If that happened, check if distinct() is + # needed to remove duplicate results. + if lookup_params_count > len(lookup_params): + use_distinct = use_distinct or lookup_needs_distinct(self.lookup_opts, field_path) if spec and spec.has_output(): filter_specs.append(spec) diff --git a/tests/admin_changelist/tests.py b/tests/admin_changelist/tests.py index c501770761b..b2292a77a07 100644 --- a/tests/admin_changelist/tests.py +++ b/tests/admin_changelist/tests.py @@ -445,6 +445,22 @@ class ChangeListTests(TestCase): # There's only one Concert instance self.assertEqual(cl.queryset.count(), 1) + def test_no_distinct_for_m2m_in_list_filter_without_params(self): + """ + If a ManyToManyField is in list_filter but isn't in any lookup params, + the changelist's query shouldn't have distinct. + """ + m = BandAdmin(Band, custom_site) + for lookup_params in ({}, {'name': 'test'}): + request = self.factory.get('/band/', lookup_params) + cl = ChangeList(request, Band, *get_changelist_args(m)) + self.assertFalse(cl.queryset.query.distinct) + + # A ManyToManyField in params does have distinct applied. + request = self.factory.get('/band/', {'genres': '0'}) + cl = ChangeList(request, Band, *get_changelist_args(m)) + self.assertTrue(cl.queryset.query.distinct) + def test_pagination(self): """ Regression tests for #12893: Pagination in admins changelist doesn't