summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2021-04-26 09:22:46 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2021-04-27 10:39:55 +0200
commit34981f399a68b633682e0f6a3ded2e31ffd6d243 (patch)
tree697d788e86de40d9bd623e8ccc09c4cfcfc28557 /django
parentfbea64b8ce6a82dd34b1f78cb884306455106185 (diff)
[3.2.x] Fixed #32682 -- Made admin changelist use Exists() instead of distinct() for preventing duplicates.
Thanks Zain Patel for the report and Simon Charette for reviews. The exception introduced in 6307c3f1a123f5975c73b231e8ac4f115fd72c0d revealed a possible data loss issue in the admin. Backport of 187118203197801c6cb72dc8b06b714b23b6dd3d from main
Diffstat (limited to 'django')
-rw-r--r--django/contrib/admin/views/main.py23
1 files changed, 12 insertions, 11 deletions
diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py
index dc43e7849d..a54ef25f23 100644
--- a/django/contrib/admin/views/main.py
+++ b/django/contrib/admin/views/main.py
@@ -17,7 +17,7 @@ from django.core.exceptions import (
FieldDoesNotExist, ImproperlyConfigured, SuspiciousOperation,
)
from django.core.paginator import InvalidPage
-from django.db.models import F, Field, ManyToOneRel, OrderBy
+from django.db.models import Exists, F, Field, ManyToOneRel, OrderBy, OuterRef
from django.db.models.expressions import Combinable
from django.urls import reverse
from django.utils.http import urlencode
@@ -472,13 +472,6 @@ class ChangeList:
# ValueError, ValidationError, or ?.
raise IncorrectLookupParameters(e)
- if not qs.query.select_related:
- qs = self.apply_select_related(qs)
-
- # Set ordering.
- ordering = self.get_ordering(request, qs)
- qs = qs.order_by(*ordering)
-
# Apply search results
qs, search_may_have_duplicates = self.model_admin.get_search_results(
request, qs, self.query,
@@ -491,9 +484,17 @@ class ChangeList:
)
# Remove duplicates from results, if necessary
if filters_may_have_duplicates | search_may_have_duplicates:
- return qs.distinct()
- else:
- return qs
+ qs = qs.filter(pk=OuterRef('pk'))
+ qs = self.root_queryset.filter(Exists(qs))
+
+ # Set ordering.
+ ordering = self.get_ordering(request, qs)
+ qs = qs.order_by(*ordering)
+
+ if not qs.query.select_related:
+ qs = self.apply_select_related(qs)
+
+ return qs
def apply_select_related(self, qs):
if self.list_select_related is True: