mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[3.1.x] Fixed #31566 -- Fixed aliases crash when chaining values()/values_list() after annotate() with aggregations and subqueries.
Subquery annotation references must be resolved if they are excluded from the GROUP BY clause by a following .values() call. Regression infb3f034f1c. Thanks Makina Corpus for the report. Backport of42c08ee465from master
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							6227173542
						
					
				
				
					commit
					8cb87a3f7c
				
			| @@ -2155,6 +2155,15 @@ class Query(BaseExpression): | |||||||
|             # SELECT clause which is about to be cleared. |             # SELECT clause which is about to be cleared. | ||||||
|             self.set_group_by(allow_aliases=False) |             self.set_group_by(allow_aliases=False) | ||||||
|             self.clear_select_fields() |             self.clear_select_fields() | ||||||
|  |         elif self.group_by: | ||||||
|  |             # Resolve GROUP BY annotation references if they are not part of | ||||||
|  |             # the selected fields anymore. | ||||||
|  |             group_by = [] | ||||||
|  |             for expr in self.group_by: | ||||||
|  |                 if isinstance(expr, Ref) and expr.refs not in field_names: | ||||||
|  |                     expr = self.annotations[expr.refs] | ||||||
|  |                 group_by.append(expr) | ||||||
|  |             self.group_by = tuple(group_by) | ||||||
|  |  | ||||||
|         self.values_select = tuple(field_names) |         self.values_select = tuple(field_names) | ||||||
|         self.add_fields(field_names, True) |         self.add_fields(field_names, True) | ||||||
|   | |||||||
| @@ -11,3 +11,7 @@ Bugfixes | |||||||
|  |  | ||||||
| * Fixed a regression in Django 3.0 by restoring the ability to use field | * Fixed a regression in Django 3.0 by restoring the ability to use field | ||||||
|   lookups in ``Meta.ordering`` (:ticket:`31538`). |   lookups in ``Meta.ordering`` (:ticket:`31538`). | ||||||
|  |  | ||||||
|  | * Fixed a regression in Django 3.0 where ``QuerySet.values()`` and | ||||||
|  |   ``values_list()`` crashed if a queryset contained an aggregation and a | ||||||
|  |   subquery annotation (:ticket:`31566`). | ||||||
|   | |||||||
| @@ -1,10 +1,13 @@ | |||||||
| import datetime | import datetime | ||||||
| from decimal import Decimal | from decimal import Decimal | ||||||
|  | from unittest import skipIf | ||||||
|  |  | ||||||
| from django.core.exceptions import FieldDoesNotExist, FieldError | from django.core.exceptions import FieldDoesNotExist, FieldError | ||||||
|  | from django.db import connection | ||||||
| from django.db.models import ( | from django.db.models import ( | ||||||
|     BooleanField, CharField, Count, DateTimeField, ExpressionWrapper, F, Func, |     BooleanField, CharField, Count, DateTimeField, Exists, ExpressionWrapper, | ||||||
|     IntegerField, NullBooleanField, OuterRef, Q, Subquery, Sum, Value, |     F, Func, IntegerField, Max, NullBooleanField, OuterRef, Q, Subquery, Sum, | ||||||
|  |     Value, | ||||||
| ) | ) | ||||||
| from django.db.models.expressions import RawSQL | from django.db.models.expressions import RawSQL | ||||||
| from django.db.models.functions import Length, Lower | from django.db.models.functions import Length, Lower | ||||||
| @@ -619,3 +622,16 @@ class NonAggregateAnnotationTestCase(TestCase): | |||||||
|             total_books=Subquery(long_books_qs, output_field=IntegerField()), |             total_books=Subquery(long_books_qs, output_field=IntegerField()), | ||||||
|         ).values('name') |         ).values('name') | ||||||
|         self.assertCountEqual(publisher_books_qs, [{'name': 'Sams'}, {'name': 'Morgan Kaufmann'}]) |         self.assertCountEqual(publisher_books_qs, [{'name': 'Sams'}, {'name': 'Morgan Kaufmann'}]) | ||||||
|  |  | ||||||
|  |     @skipIf(connection.vendor == 'oracle', 'See https://code.djangoproject.com/ticket/31584') | ||||||
|  |     def test_annotation_exists_aggregate_values_chaining(self): | ||||||
|  |         qs = Book.objects.values('publisher').annotate( | ||||||
|  |             has_authors=Exists(Book.authors.through.objects.filter(book=OuterRef('pk'))), | ||||||
|  |             max_pubdate=Max('pubdate'), | ||||||
|  |         ).values_list('max_pubdate', flat=True).order_by('max_pubdate') | ||||||
|  |         self.assertCountEqual(qs, [ | ||||||
|  |             datetime.date(1991, 10, 15), | ||||||
|  |             datetime.date(2008, 3, 3), | ||||||
|  |             datetime.date(2008, 6, 23), | ||||||
|  |             datetime.date(2008, 11, 3), | ||||||
|  |         ]) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user