diff --git a/django/contrib/postgres/aggregates/general.py b/django/contrib/postgres/aggregates/general.py index ae432a016c..99fe0d8739 100644 --- a/django/contrib/postgres/aggregates/general.py +++ b/django/contrib/postgres/aggregates/general.py @@ -1,7 +1,9 @@ import warnings from django.contrib.postgres.fields import ArrayField -from django.db.models import Aggregate, BooleanField, JSONField, Value +from django.db.models import ( + Aggregate, BooleanField, JSONField, TextField, Value, +) from django.utils.deprecation import RemovedInDjango50Warning from .mixins import OrderableAggMixin @@ -88,6 +90,7 @@ class StringAgg(DeprecatedConvertValueMixin, OrderableAggMixin, Aggregate): function = 'STRING_AGG' template = '%(function)s(%(distinct)s%(expressions)s %(ordering)s)' allow_distinct = True + output_field = TextField() # RemovedInDjango50Warning deprecation_value = '' diff --git a/tests/postgres_tests/migrations/0002_create_test_models.py b/tests/postgres_tests/migrations/0002_create_test_models.py index 1ce875441b..32f99ed6bb 100644 --- a/tests/postgres_tests/migrations/0002_create_test_models.py +++ b/tests/postgres_tests/migrations/0002_create_test_models.py @@ -202,6 +202,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('boolean_field', models.BooleanField(null=True)), ('char_field', models.CharField(max_length=30, blank=True)), + ('text_field', models.TextField(blank=True)), ('integer_field', models.IntegerField(null=True)), ('json_field', models.JSONField(null=True)), ], diff --git a/tests/postgres_tests/models.py b/tests/postgres_tests/models.py index ddae9d1edb..fa20378071 100644 --- a/tests/postgres_tests/models.py +++ b/tests/postgres_tests/models.py @@ -160,6 +160,7 @@ class AggregateTestModel(PostgreSQLModel): To test postgres-specific general aggregation functions """ char_field = models.CharField(max_length=30, blank=True) + text_field = models.TextField(blank=True) integer_field = models.IntegerField(null=True) boolean_field = models.BooleanField(null=True) json_field = models.JSONField(null=True) diff --git a/tests/postgres_tests/test_aggregates.py b/tests/postgres_tests/test_aggregates.py index a963aae3c4..07200f9f97 100644 --- a/tests/postgres_tests/test_aggregates.py +++ b/tests/postgres_tests/test_aggregates.py @@ -25,22 +25,30 @@ class TestGeneralAggregate(PostgreSQLTestCase): @classmethod def setUpTestData(cls): cls.aggs = AggregateTestModel.objects.bulk_create([ - AggregateTestModel(boolean_field=True, char_field='Foo1', integer_field=0), + AggregateTestModel( + boolean_field=True, + char_field='Foo1', + text_field='Text1', + integer_field=0, + ), AggregateTestModel( boolean_field=False, char_field='Foo2', + text_field='Text2', integer_field=1, json_field={'lang': 'pl'}, ), AggregateTestModel( boolean_field=False, char_field='Foo4', + text_field='Text4', integer_field=2, json_field={'lang': 'en'}, ), AggregateTestModel( boolean_field=True, char_field='Foo3', + text_field='Text3', integer_field=0, json_field={'breed': 'collie'}, ), @@ -299,6 +307,12 @@ class TestGeneralAggregate(PostgreSQLTestCase): values = AggregateTestModel.objects.aggregate(stringagg=StringAgg('char_field', delimiter=';')) self.assertEqual(values, {'stringagg': 'Foo1;Foo2;Foo4;Foo3'}) + def test_string_agg_default_output_field(self): + values = AggregateTestModel.objects.aggregate( + stringagg=StringAgg('text_field', delimiter=';'), + ) + self.assertEqual(values, {'stringagg': 'Text1;Text2;Text4;Text3'}) + def test_string_agg_charfield_ordering(self): ordering_test_cases = ( (F('char_field').desc(), 'Foo4;Foo3;Foo2;Foo1'),