소스 검색

Fixed #25095 -- Fixed annotate() + values() group by bug

Thanks Josh Smeaton for help on the tests.
Mitchell Kotler 9 년 전
부모
커밋
6024fd5dc2
2개의 변경된 파일33개의 추가작업 그리고 2개의 파일을 삭제
  1. 2 2
      django/db/models/sql/query.py
  2. 31 0
      tests/aggregation/tests.py

+ 2 - 2
django/db/models/sql/query.py

@@ -1679,8 +1679,8 @@ class Query(object):
         for col in self.select:
             self.group_by.append(col)
 
-        if self._annotations:
-            for alias, annotation in six.iteritems(self.annotations):
+        if self.annotation_select:
+            for alias, annotation in six.iteritems(self.annotation_select):
                 for col in annotation.get_group_by_cols():
                     self.group_by.append(col)
 

+ 31 - 0
tests/aggregation/tests.py

@@ -395,6 +395,37 @@ class AggregateTestCase(TestCase):
         vals = Book.objects.aggregate(Count("rating", distinct=True))
         self.assertEqual(vals, {"rating__count": 4})
 
+    def test_non_grouped_annotation_not_in_group_by(self):
+        """
+        An annotation not included in values() before an aggregate should be
+        excluded from the group by clause.
+        """
+        qs = (
+            Book.objects.annotate(xprice=F('price')).filter(rating=4.0).values('rating')
+                .annotate(count=Count('publisher_id', distinct=True)).values('count', 'rating').order_by('count')
+        )
+        self.assertEqual(
+            list(qs), [
+                {'rating': 4.0, 'count': 2},
+            ]
+        )
+
+    def test_grouped_annotation_in_group_by(self):
+        """
+        An annotation included in values() before an aggregate should be
+        included in the group by clause.
+        """
+        qs = (
+            Book.objects.annotate(xprice=F('price')).filter(rating=4.0).values('rating', 'xprice')
+                .annotate(count=Count('publisher_id', distinct=True)).values('count', 'rating').order_by('count')
+        )
+        self.assertEqual(
+            list(qs), [
+                {'rating': 4.0, 'count': 1},
+                {'rating': 4.0, 'count': 2},
+            ]
+        )
+
     def test_fkey_aggregate(self):
         explicit = list(Author.objects.annotate(Count('book__id')))
         implicit = list(Author.objects.annotate(Count('book')))