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. | ||||
|             self.set_group_by(allow_aliases=False) | ||||
|             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.add_fields(field_names, True) | ||||
|   | ||||
| @@ -11,3 +11,7 @@ Bugfixes | ||||
|  | ||||
| * Fixed a regression in Django 3.0 by restoring the ability to use field | ||||
|   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 | ||||
| from decimal import Decimal | ||||
| from unittest import skipIf | ||||
|  | ||||
| from django.core.exceptions import FieldDoesNotExist, FieldError | ||||
| from django.db import connection | ||||
| from django.db.models import ( | ||||
|     BooleanField, CharField, Count, DateTimeField, ExpressionWrapper, F, Func, | ||||
|     IntegerField, NullBooleanField, OuterRef, Q, Subquery, Sum, Value, | ||||
|     BooleanField, CharField, Count, DateTimeField, Exists, ExpressionWrapper, | ||||
|     F, Func, IntegerField, Max, NullBooleanField, OuterRef, Q, Subquery, Sum, | ||||
|     Value, | ||||
| ) | ||||
| from django.db.models.expressions import RawSQL | ||||
| from django.db.models.functions import Length, Lower | ||||
| @@ -619,3 +622,16 @@ class NonAggregateAnnotationTestCase(TestCase): | ||||
|             total_books=Subquery(long_books_qs, output_field=IntegerField()), | ||||
|         ).values('name') | ||||
|         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