Skip to content

Commit d734f16

Browse files
camuthigsarahboyce
authored andcommitted
Refs #35444 -- Deprecated contrib.postgres aggregates ordering for order_by.
Aligns the argument with SQL standards already used in Window.order_by and sets up for adding support to Aggregate.
1 parent 46b3e7d commit d734f16

File tree

7 files changed

+137
-65
lines changed

7 files changed

+137
-65
lines changed

django/contrib/postgres/aggregates/general.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
class ArrayAgg(OrderableAggMixin, Aggregate):
1919
function = "ARRAY_AGG"
20-
template = "%(function)s(%(distinct)s%(expressions)s %(ordering)s)"
20+
template = "%(function)s(%(distinct)s%(expressions)s %(order_by)s)"
2121
allow_distinct = True
2222

2323
@property
@@ -49,14 +49,14 @@ class BoolOr(Aggregate):
4949

5050
class JSONBAgg(OrderableAggMixin, Aggregate):
5151
function = "JSONB_AGG"
52-
template = "%(function)s(%(distinct)s%(expressions)s %(ordering)s)"
52+
template = "%(function)s(%(distinct)s%(expressions)s %(order_by)s)"
5353
allow_distinct = True
5454
output_field = JSONField()
5555

5656

5757
class StringAgg(OrderableAggMixin, Aggregate):
5858
function = "STRING_AGG"
59-
template = "%(function)s(%(distinct)s%(expressions)s %(ordering)s)"
59+
template = "%(function)s(%(distinct)s%(expressions)s %(order_by)s)"
6060
allow_distinct = True
6161
output_field = TextField()
6262

django/contrib/postgres/aggregates/mixins.py

+24-9
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,30 @@
1+
import warnings
2+
13
from django.core.exceptions import FullResultSet
24
from django.db.models.expressions import OrderByList
5+
from django.utils.deprecation import RemovedInDjango61Warning
36

47

58
class OrderableAggMixin:
6-
def __init__(self, *expressions, ordering=(), **extra):
7-
if not ordering:
9+
# RemovedInDjango61Warning: When the deprecation ends, replace with:
10+
# def __init__(self, *expressions, order_by=(), **extra):
11+
def __init__(self, *expressions, ordering=(), order_by=(), **extra):
12+
# RemovedInDjango61Warning.
13+
if ordering:
14+
warnings.warn(
15+
"The ordering argument is deprecated. Use order_by instead.",
16+
category=RemovedInDjango61Warning,
17+
stacklevel=2,
18+
)
19+
if order_by:
20+
raise TypeError("Cannot specify both order_by and ordering.")
21+
order_by = ordering
22+
if not order_by:
823
self.order_by = None
9-
elif isinstance(ordering, (list, tuple)):
10-
self.order_by = OrderByList(*ordering)
24+
elif isinstance(order_by, (list, tuple)):
25+
self.order_by = OrderByList(*order_by)
1126
else:
12-
self.order_by = OrderByList(ordering)
27+
self.order_by = OrderByList(order_by)
1328
super().__init__(*expressions, **extra)
1429

1530
def resolve_expression(self, *args, **kwargs):
@@ -25,12 +40,12 @@ def set_source_expressions(self, exprs):
2540
return super().set_source_expressions(exprs)
2641

2742
def as_sql(self, compiler, connection):
28-
*source_exprs, filtering_expr, ordering_expr = self.get_source_expressions()
43+
*source_exprs, filtering_expr, order_by_expr = self.get_source_expressions()
2944

3045
order_by_sql = ""
3146
order_by_params = []
32-
if ordering_expr is not None:
33-
order_by_sql, order_by_params = compiler.compile(ordering_expr)
47+
if order_by_expr is not None:
48+
order_by_sql, order_by_params = compiler.compile(order_by_expr)
3449

3550
filter_params = []
3651
if filtering_expr is not None:
@@ -43,5 +58,5 @@ def as_sql(self, compiler, connection):
4358
for source_expr in source_exprs:
4459
source_params += compiler.compile(source_expr)[1]
4560

46-
sql, _ = super().as_sql(compiler, connection, ordering=order_by_sql)
61+
sql, _ = super().as_sql(compiler, connection, order_by=order_by_sql)
4762
return sql, (*source_params, *order_by_params, *filter_params)

docs/internals/deprecation.txt

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ details on these changes.
2222
``django.contrib.auth.login()`` and ``django.contrib.auth.alogin()`` will be
2323
removed.
2424

25+
* The ``ordering`` keyword argument of the PostgreSQL specific aggregation
26+
functions ``django.contrib.postgres.aggregates.ArrayAgg``,
27+
``django.contrib.postgres.aggregates.JSONBAgg``, and
28+
``django.contrib.postgres.aggregates.StringAgg`` will be removed.
29+
2530
.. _deprecation-removed-in-6.0:
2631

2732
6.0

docs/ref/contrib/postgres/aggregates.txt

+31-10
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ General-purpose aggregation functions
3030
``ArrayAgg``
3131
------------
3232

33-
.. class:: ArrayAgg(expression, distinct=False, filter=None, default=None, ordering=(), **extra)
33+
.. class:: ArrayAgg(expression, distinct=False, filter=None, default=None, order_by=(), **extra)
3434

3535
Returns a list of values, including nulls, concatenated into an array, or
3636
``default`` if there are no values.
@@ -40,7 +40,9 @@ General-purpose aggregation functions
4040
An optional boolean argument that determines if array values
4141
will be distinct. Defaults to ``False``.
4242

43-
.. attribute:: ordering
43+
.. attribute:: order_by
44+
45+
.. versionadded:: 5.2
4446

4547
An optional string of a field name (with an optional ``"-"`` prefix
4648
which indicates descending order) or an expression (or a tuple or list
@@ -55,6 +57,11 @@ General-purpose aggregation functions
5557

5658
F("some_field").desc()
5759

60+
.. deprecated:: 5.2
61+
62+
The ``ordering`` keyword argument is deprecated. Use
63+
:attr:`ArrayAgg.order_by` instead.
64+
5865
``BitAnd``
5966
----------
6067

@@ -130,7 +137,7 @@ General-purpose aggregation functions
130137
``JSONBAgg``
131138
------------
132139

133-
.. class:: JSONBAgg(expressions, distinct=False, filter=None, default=None, ordering=(), **extra)
140+
.. class:: JSONBAgg(expressions, distinct=False, filter=None, default=None, order_by=(), **extra)
134141

135142
Returns the input values as a ``JSON`` array, or ``default`` if there are
136143
no values. You can query the result using :lookup:`key and index lookups
@@ -141,14 +148,16 @@ General-purpose aggregation functions
141148
An optional boolean argument that determines if array values will be
142149
distinct. Defaults to ``False``.
143150

144-
.. attribute:: ordering
151+
.. attribute:: order_by
152+
153+
.. versionadded:: 5.2
145154

146155
An optional string of a field name (with an optional ``"-"`` prefix
147156
which indicates descending order) or an expression (or a tuple or list
148157
of strings and/or expressions) that specifies the ordering of the
149158
elements in the result list.
150159

151-
Examples are the same as for :attr:`ArrayAgg.ordering`.
160+
Examples are the same as for :attr:`ArrayAgg.order_by`.
152161

153162
Usage example::
154163

@@ -168,18 +177,23 @@ General-purpose aggregation functions
168177
>>> Room.objects.annotate(
169178
... requirements=JSONBAgg(
170179
... "hotelreservation__requirements",
171-
... ordering="-hotelreservation__start",
180+
... order_by="-hotelreservation__start",
172181
... )
173182
... ).filter(requirements__0__sea_view=True).values("number", "requirements")
174183
<QuerySet [{'number': 102, 'requirements': [
175184
{'parking': False, 'sea_view': True, 'double_bed': False},
176185
{'parking': True, 'double_bed': True}
177186
]}]>
178187

188+
.. deprecated:: 5.2
189+
190+
The ``ordering`` keyword argument is deprecated. Use
191+
:attr:`JSONBAgg.order_by` instead.
192+
179193
``StringAgg``
180194
-------------
181195

182-
.. class:: StringAgg(expression, delimiter, distinct=False, filter=None, default=None, ordering=())
196+
.. class:: StringAgg(expression, delimiter, distinct=False, filter=None, default=None, order_by=())
183197

184198
Returns the input values concatenated into a string, separated by
185199
the ``delimiter`` string, or ``default`` if there are no values.
@@ -193,14 +207,16 @@ General-purpose aggregation functions
193207
An optional boolean argument that determines if concatenated values
194208
will be distinct. Defaults to ``False``.
195209

196-
.. attribute:: ordering
210+
.. attribute:: order_by
211+
212+
.. versionadded:: 5.2
197213

198214
An optional string of a field name (with an optional ``"-"`` prefix
199215
which indicates descending order) or an expression (or a tuple or list
200216
of strings and/or expressions) that specifies the ordering of the
201217
elements in the result string.
202218

203-
Examples are the same as for :attr:`ArrayAgg.ordering`.
219+
Examples are the same as for :attr:`ArrayAgg.order_by`.
204220

205221
Usage example::
206222

@@ -224,13 +240,18 @@ General-purpose aggregation functions
224240
... publication_names=StringAgg(
225241
... "publications__title",
226242
... delimiter=", ",
227-
... ordering="publications__title",
243+
... order_by="publications__title",
228244
... )
229245
... ).values("headline", "publication_names")
230246
<QuerySet [{
231247
'headline': 'NASA uses Python', 'publication_names': 'Science News, The Python Journal'
232248
}]>
233249

250+
.. deprecated:: 5.2
251+
252+
The ``ordering`` keyword argument is deprecated. Use
253+
:attr:`StringAgg.order_by` instead.
254+
234255
Aggregate functions for statistics
235256
==================================
236257

docs/releases/3.2.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ Minor features
250250
* The new ``ExclusionConstraint.opclasses`` attribute allows setting PostgreSQL
251251
operator classes.
252252

253-
* The new :attr:`.JSONBAgg.ordering` attribute determines the ordering of the
253+
* The new ``JSONBAgg.ordering`` attribute determines the ordering of the
254254
aggregated elements.
255255

256256
* The new :attr:`.JSONBAgg.distinct` attribute determines if aggregated values

docs/releases/5.2.txt

+6
Original file line numberDiff line numberDiff line change
@@ -495,3 +495,9 @@ Miscellaneous
495495
* The fallback to ``request.user`` when ``user`` is ``None`` in
496496
``django.contrib.auth.login()`` and ``django.contrib.auth.alogin()`` will be
497497
removed.
498+
499+
* The ``ordering`` keyword argument of the PostgreSQL specific aggregation
500+
functions ``django.contrib.postgres.aggregates.ArrayAgg``,
501+
``django.contrib.postgres.aggregates.JSONBAgg``, and
502+
``django.contrib.postgres.aggregates.StringAgg`` is deprecated in favor
503+
of the ``order_by`` argument.

0 commit comments

Comments
 (0)