summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Beaulé <beauleetienne0@gmail.com>2019-07-30 20:08:55 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2019-07-31 11:22:50 +0200
commit5f24e7158e1d5a7e40fa0ae270639f6a171bb18e (patch)
tree36b249e5a101df5f3494be9000db857e5af9c3d1
parentcb3c2da12858004c805fc511a9c2eb0f91fb73c7 (diff)
Fixed #30665 -- Added support for distinct argument to Avg() and Sum().
-rw-r--r--django/db/models/aggregates.py2
-rw-r--r--docs/ref/models/querysets.txt28
-rw-r--r--docs/releases/3.0.txt3
-rw-r--r--tests/aggregation/tests.py10
4 files changed, 39 insertions, 4 deletions
diff --git a/django/db/models/aggregates.py b/django/db/models/aggregates.py
index da4ff928aa..8b10829eb8 100644
--- a/django/db/models/aggregates.py
+++ b/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):
diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
index f84097ae96..409d8f0f29 100644
--- a/docs/ref/models/querysets.txt
+++ b/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``
~~~~~~~~~~~~
diff --git a/docs/releases/3.0.txt b/docs/releases/3.0.txt
index 4bfebba73b..da1578c0eb 100644
--- a/docs/releases/3.0.txt
+++ b/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
~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/aggregation/tests.py b/tests/aggregation/tests.py
index 7e0436cdfc..0f799c4bc3 100644
--- a/tests/aggregation/tests.py
+++ b/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):
"""