Преглед на файлове

Fixed #30665 -- Added support for distinct argument to Avg() and Sum().

Étienne Beaulé преди 5 години
родител
ревизия
5f24e7158e
променени са 4 файла, в които са добавени 39 реда и са изтрити 4 реда
  1. 2 0
      django/db/models/aggregates.py
  2. 26 2
      docs/ref/models/querysets.txt
  3. 3 0
      docs/releases/3.0.txt
  4. 8 2
      tests/aggregation/tests.py

+ 2 - 0
django/db/models/aggregates.py

@@ -99,6 +99,7 @@ class Aggregate(Func):
 class Avg(FixDurationInputMixin, NumericOutputFieldMixin, Aggregate):
     function = 'AVG'
     name = 'Avg'
+    allow_distinct = True
 
 
 class Count(Aggregate):
@@ -142,6 +143,7 @@ class StdDev(NumericOutputFieldMixin, Aggregate):
 class Sum(FixDurationInputMixin, Aggregate):
     function = 'SUM'
     name = 'Sum'
+    allow_distinct = True
 
 
 class Variance(NumericOutputFieldMixin, Aggregate):

+ 26 - 2
docs/ref/models/querysets.txt

@@ -3378,7 +3378,7 @@ by the aggregate.
 ``Avg``
 ~~~~~~~
 
-.. class:: Avg(expression, output_field=None, filter=None, **extra)
+.. class:: Avg(expression, output_field=None, distinct=False, filter=None, **extra)
 
     Returns the mean value of the given expression, which must be numeric
     unless you specify a different ``output_field``.
@@ -3387,6 +3387,18 @@ by the aggregate.
     * Return type: ``float`` if input is ``int``, otherwise same as input
       field, or ``output_field`` if supplied
 
+    Has one optional argument:
+
+    .. attribute:: distinct
+
+        If ``distinct=True``, ``Avg`` returns the mean value of unique values.
+        This is the SQL equivalent of ``AVG(DISTINCT <field>)``. The default
+        value is ``False``.
+
+    .. versionchanged:: 3.0
+
+        Support for ``distinct=True`` was added.
+
 ``Count``
 ~~~~~~~~~
 
@@ -3451,13 +3463,25 @@ by the aggregate.
 ``Sum``
 ~~~~~~~
 
-.. class:: Sum(expression, output_field=None, filter=None, **extra)
+.. class:: Sum(expression, output_field=None, distinct=False, filter=None, **extra)
 
     Computes the sum of all values of the given expression.
 
     * Default alias: ``<field>__sum``
     * Return type: same as input field, or ``output_field`` if supplied
 
+    Has one optional argument:
+
+    .. attribute:: distinct
+
+        If ``distinct=True``, ``Sum`` returns the sum of unique values. This is
+        the SQL equivalent of ``SUM(DISTINCT <field>)``. The default value is
+        ``False``.
+
+    .. versionchanged:: 3.0
+
+        Support for ``distinct=True`` was added.
+
 ``Variance``
 ~~~~~~~~~~~~
 

+ 3 - 0
docs/releases/3.0.txt

@@ -291,6 +291,9 @@ Models
   customize the get and set behavior by overriding their
   :py:ref:`descriptors <descriptors>`.
 
+* :class:`~django.db.models.Avg` and :class:`~django.db.models.Sum` now support
+  the ``distinct`` argument.
+
 Requests and Responses
 ~~~~~~~~~~~~~~~~~~~~~~
 

+ 8 - 2
tests/aggregation/tests.py

@@ -401,8 +401,14 @@ class AggregateTestCase(TestCase):
         self.assertEqual(aggs['distinct_ratings'], 4)
 
     def test_distinct_on_aggregate(self):
-        books = Book.objects.aggregate(ratings=Count('rating', distinct=True))
-        self.assertEqual(books['ratings'], 4)
+        for aggregate, expected_result in (
+            (Avg, 4.125),
+            (Count, 4),
+            (Sum, 16.5),
+        ):
+            with self.subTest(aggregate=aggregate.__name__):
+                books = Book.objects.aggregate(ratings=aggregate('rating', distinct=True))
+                self.assertEqual(books['ratings'], expected_result)
 
     def test_non_grouped_annotation_not_in_group_by(self):
         """