mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	[3.2.x] 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.
Backport of cd74aad90e from main
			
			
This commit is contained in:
		| @@ -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 | ||||||
|   | |||||||
| @@ -1586,14 +1586,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 | ||||||
|   | |||||||
| @@ -660,14 +660,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): | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user