mirror of https://github.com/django/django.git
Refs #32682 -- Renamed use_distinct variable to may_have_duplicates.
QuerySet.distinct() is not the only way to avoid duplicate, it's also not preferred.
This commit is contained in:
parent
4074f38e1d
commit
cd74aad90e
|
@ -1019,7 +1019,7 @@ class ModelAdmin(BaseModelAdmin):
|
||||||
# Otherwise, use the field with icontains.
|
# Otherwise, use the field with icontains.
|
||||||
return "%s__icontains" % field_name
|
return "%s__icontains" % field_name
|
||||||
|
|
||||||
use_distinct = False
|
may_have_duplicates = False
|
||||||
search_fields = self.get_search_fields(request)
|
search_fields = self.get_search_fields(request)
|
||||||
if search_fields and search_term:
|
if search_fields and search_term:
|
||||||
orm_lookups = [construct_search(str(search_field))
|
orm_lookups = [construct_search(str(search_field))
|
||||||
|
@ -1030,9 +1030,11 @@ class ModelAdmin(BaseModelAdmin):
|
||||||
or_queries = [models.Q(**{orm_lookup: bit})
|
or_queries = [models.Q(**{orm_lookup: bit})
|
||||||
for orm_lookup in orm_lookups]
|
for orm_lookup in orm_lookups]
|
||||||
queryset = queryset.filter(reduce(operator.or_, or_queries))
|
queryset = queryset.filter(reduce(operator.or_, or_queries))
|
||||||
use_distinct |= any(lookup_needs_distinct(self.opts, search_spec) for search_spec in orm_lookups)
|
may_have_duplicates |= any(
|
||||||
|
lookup_needs_distinct(self.opts, search_spec)
|
||||||
return queryset, use_distinct
|
for search_spec in orm_lookups
|
||||||
|
)
|
||||||
|
return queryset, may_have_duplicates
|
||||||
|
|
||||||
def get_preserved_filters(self, request):
|
def get_preserved_filters(self, request):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -122,7 +122,7 @@ class ChangeList:
|
||||||
|
|
||||||
def get_filters(self, request):
|
def get_filters(self, request):
|
||||||
lookup_params = self.get_filters_params()
|
lookup_params = self.get_filters_params()
|
||||||
use_distinct = False
|
may_have_duplicates = False
|
||||||
has_active_filters = False
|
has_active_filters = False
|
||||||
|
|
||||||
for key, value in lookup_params.items():
|
for key, value in lookup_params.items():
|
||||||
|
@ -157,7 +157,7 @@ class ChangeList:
|
||||||
# processes. If that happened, check if distinct() is needed to
|
# processes. If that happened, check if distinct() is needed to
|
||||||
# remove duplicate results.
|
# remove duplicate results.
|
||||||
if lookup_params_count > len(lookup_params):
|
if lookup_params_count > len(lookup_params):
|
||||||
use_distinct = use_distinct or lookup_needs_distinct(self.lookup_opts, field_path)
|
may_have_duplicates |= lookup_needs_distinct(self.lookup_opts, field_path)
|
||||||
if spec and spec.has_output():
|
if spec and spec.has_output():
|
||||||
filter_specs.append(spec)
|
filter_specs.append(spec)
|
||||||
if lookup_params_count > len(lookup_params):
|
if lookup_params_count > len(lookup_params):
|
||||||
|
@ -203,9 +203,9 @@ class ChangeList:
|
||||||
try:
|
try:
|
||||||
for key, value in lookup_params.items():
|
for key, value in lookup_params.items():
|
||||||
lookup_params[key] = prepare_lookup_value(key, value)
|
lookup_params[key] = prepare_lookup_value(key, value)
|
||||||
use_distinct = use_distinct or lookup_needs_distinct(self.lookup_opts, key)
|
may_have_duplicates |= lookup_needs_distinct(self.lookup_opts, key)
|
||||||
return (
|
return (
|
||||||
filter_specs, bool(filter_specs), lookup_params, use_distinct,
|
filter_specs, bool(filter_specs), lookup_params, may_have_duplicates,
|
||||||
has_active_filters,
|
has_active_filters,
|
||||||
)
|
)
|
||||||
except FieldDoesNotExist as e:
|
except FieldDoesNotExist as e:
|
||||||
|
@ -445,7 +445,7 @@ class ChangeList:
|
||||||
self.filter_specs,
|
self.filter_specs,
|
||||||
self.has_filters,
|
self.has_filters,
|
||||||
remaining_lookup_params,
|
remaining_lookup_params,
|
||||||
filters_use_distinct,
|
filters_may_have_duplicates,
|
||||||
self.has_active_filters,
|
self.has_active_filters,
|
||||||
) = self.get_filters(request)
|
) = self.get_filters(request)
|
||||||
# Then, we let every list filter modify the queryset to its liking.
|
# Then, we let every list filter modify the queryset to its liking.
|
||||||
|
@ -480,7 +480,9 @@ class ChangeList:
|
||||||
qs = qs.order_by(*ordering)
|
qs = qs.order_by(*ordering)
|
||||||
|
|
||||||
# Apply search results
|
# Apply search results
|
||||||
qs, search_use_distinct = self.model_admin.get_search_results(request, qs, self.query)
|
qs, search_may_have_duplicates = self.model_admin.get_search_results(
|
||||||
|
request, qs, self.query,
|
||||||
|
)
|
||||||
|
|
||||||
# Set query string for clearing all filters.
|
# Set query string for clearing all filters.
|
||||||
self.clear_all_filters_qs = self.get_query_string(
|
self.clear_all_filters_qs = self.get_query_string(
|
||||||
|
@ -488,7 +490,7 @@ class ChangeList:
|
||||||
remove=self.get_filters_params(),
|
remove=self.get_filters_params(),
|
||||||
)
|
)
|
||||||
# Remove duplicates from results, if necessary
|
# Remove duplicates from results, if necessary
|
||||||
if filters_use_distinct | search_use_distinct:
|
if filters_may_have_duplicates | search_may_have_duplicates:
|
||||||
return qs.distinct()
|
return qs.distinct()
|
||||||
else:
|
else:
|
||||||
return qs
|
return qs
|
||||||
|
|
|
@ -1576,14 +1576,16 @@ templates used by the :class:`ModelAdmin` views:
|
||||||
search_fields = ('name',)
|
search_fields = ('name',)
|
||||||
|
|
||||||
def get_search_results(self, request, queryset, search_term):
|
def get_search_results(self, request, queryset, search_term):
|
||||||
queryset, use_distinct = super().get_search_results(request, queryset, search_term)
|
queryset, may_have_duplicates = super().get_search_results(
|
||||||
|
request, queryset, search_term,
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
search_term_as_int = int(search_term)
|
search_term_as_int = int(search_term)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
queryset |= self.model.objects.filter(age=search_term_as_int)
|
queryset |= self.model.objects.filter(age=search_term_as_int)
|
||||||
return queryset, use_distinct
|
return queryset, may_have_duplicates
|
||||||
|
|
||||||
This implementation is more efficient than ``search_fields =
|
This implementation is more efficient than ``search_fields =
|
||||||
('name', '=age')`` which results in a string comparison for the numeric
|
('name', '=age')`` which results in a string comparison for the numeric
|
||||||
|
|
|
@ -653,14 +653,16 @@ class PluggableSearchPersonAdmin(admin.ModelAdmin):
|
||||||
search_fields = ('name',)
|
search_fields = ('name',)
|
||||||
|
|
||||||
def get_search_results(self, request, queryset, search_term):
|
def get_search_results(self, request, queryset, search_term):
|
||||||
queryset, use_distinct = super().get_search_results(request, queryset, search_term)
|
queryset, may_have_duplicates = super().get_search_results(
|
||||||
|
request, queryset, search_term,
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
search_term_as_int = int(search_term)
|
search_term_as_int = int(search_term)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
queryset |= self.model.objects.filter(age=search_term_as_int)
|
queryset |= self.model.objects.filter(age=search_term_as_int)
|
||||||
return queryset, use_distinct
|
return queryset, may_have_duplicates
|
||||||
|
|
||||||
|
|
||||||
class AlbumAdmin(admin.ModelAdmin):
|
class AlbumAdmin(admin.ModelAdmin):
|
||||||
|
|
Loading…
Reference in New Issue