mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	Refs #10929 -- Stopped forcing empty result value by PostgreSQL aggregates.
Per deprecation timeline.
This commit is contained in:
		| @@ -3,7 +3,7 @@ import warnings | ||||
|  | ||||
| from django.contrib.postgres.fields import ArrayField | ||||
| from django.db.models import Aggregate, BooleanField, JSONField, TextField, Value | ||||
| from django.utils.deprecation import RemovedInDjango50Warning, RemovedInDjango51Warning | ||||
| from django.utils.deprecation import RemovedInDjango51Warning | ||||
|  | ||||
| from .mixins import OrderableAggMixin | ||||
|  | ||||
| @@ -19,47 +19,11 @@ __all__ = [ | ||||
| ] | ||||
|  | ||||
|  | ||||
| # RemovedInDjango50Warning | ||||
| NOT_PROVIDED = object() | ||||
|  | ||||
|  | ||||
| class DeprecatedConvertValueMixin: | ||||
|     def __init__(self, *expressions, default=NOT_PROVIDED, **extra): | ||||
|         if default is NOT_PROVIDED: | ||||
|             default = None | ||||
|             self._default_provided = False | ||||
|         else: | ||||
|             self._default_provided = True | ||||
|         super().__init__(*expressions, default=default, **extra) | ||||
|  | ||||
|     def resolve_expression(self, *args, **kwargs): | ||||
|         resolved = super().resolve_expression(*args, **kwargs) | ||||
|         if not self._default_provided: | ||||
|             resolved.empty_result_set_value = getattr( | ||||
|                 self, "deprecation_empty_result_set_value", self.deprecation_value | ||||
|             ) | ||||
|         return resolved | ||||
|  | ||||
|     def convert_value(self, value, expression, connection): | ||||
|         if value is None and not self._default_provided: | ||||
|             warnings.warn(self.deprecation_msg, category=RemovedInDjango50Warning) | ||||
|             return self.deprecation_value | ||||
|         return value | ||||
|  | ||||
|  | ||||
| class ArrayAgg(DeprecatedConvertValueMixin, OrderableAggMixin, Aggregate): | ||||
| class ArrayAgg(OrderableAggMixin, Aggregate): | ||||
|     function = "ARRAY_AGG" | ||||
|     template = "%(function)s(%(distinct)s%(expressions)s %(ordering)s)" | ||||
|     allow_distinct = True | ||||
|  | ||||
|     # RemovedInDjango50Warning | ||||
|     deprecation_value = property(lambda self: []) | ||||
|     deprecation_msg = ( | ||||
|         "In Django 5.0, ArrayAgg() will return None instead of an empty list " | ||||
|         "if there are no rows. Pass default=None to opt into the new behavior " | ||||
|         "and silence this warning or default=[] to keep the previous behavior." | ||||
|     ) | ||||
|  | ||||
|     @property | ||||
|     def output_field(self): | ||||
|         return ArrayField(self.source_expressions[0].output_field) | ||||
| @@ -87,27 +51,14 @@ class BoolOr(Aggregate): | ||||
|     output_field = BooleanField() | ||||
|  | ||||
|  | ||||
| class JSONBAgg(DeprecatedConvertValueMixin, OrderableAggMixin, Aggregate): | ||||
| class JSONBAgg(OrderableAggMixin, Aggregate): | ||||
|     function = "JSONB_AGG" | ||||
|     template = "%(function)s(%(distinct)s%(expressions)s %(ordering)s)" | ||||
|     allow_distinct = True | ||||
|     output_field = JSONField() | ||||
|  | ||||
|     # RemovedInDjango50Warning | ||||
|     deprecation_value = "[]" | ||||
|     deprecation_empty_result_set_value = property(lambda self: []) | ||||
|     deprecation_msg = ( | ||||
|         "In Django 5.0, JSONBAgg() will return None instead of an empty list " | ||||
|         "if there are no rows. Pass default=None to opt into the new behavior " | ||||
|         "and silence this warning or default=[] to keep the previous " | ||||
|         "behavior." | ||||
|     ) | ||||
|  | ||||
|     # RemovedInDjango51Warning: When the deprecation ends, remove __init__(). | ||||
|     # | ||||
|     # RemovedInDjango50Warning: When the deprecation ends, replace with: | ||||
|     # def __init__(self, *expressions, default=None, **extra): | ||||
|     def __init__(self, *expressions, default=NOT_PROVIDED, **extra): | ||||
|     def __init__(self, *expressions, default=None, **extra): | ||||
|         super().__init__(*expressions, default=default, **extra) | ||||
|         if ( | ||||
|             isinstance(default, Value) | ||||
| @@ -136,20 +87,12 @@ class JSONBAgg(DeprecatedConvertValueMixin, OrderableAggMixin, Aggregate): | ||||
|                 ) | ||||
|  | ||||
|  | ||||
| class StringAgg(DeprecatedConvertValueMixin, OrderableAggMixin, Aggregate): | ||||
| class StringAgg(OrderableAggMixin, Aggregate): | ||||
|     function = "STRING_AGG" | ||||
|     template = "%(function)s(%(distinct)s%(expressions)s %(ordering)s)" | ||||
|     allow_distinct = True | ||||
|     output_field = TextField() | ||||
|  | ||||
|     # RemovedInDjango50Warning | ||||
|     deprecation_value = "" | ||||
|     deprecation_msg = ( | ||||
|         "In Django 5.0, StringAgg() will return None instead of an empty " | ||||
|         "string if there are no rows. Pass default=None to opt into the new " | ||||
|         'behavior and silence this warning or default="" to keep the previous behavior.' | ||||
|     ) | ||||
|  | ||||
|     def __init__(self, expression, delimiter, **extra): | ||||
|         delimiter_expr = Value(str(delimiter)) | ||||
|         super().__init__(expression, delimiter_expr, **extra) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user