mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Refs #33308 -- Removed support for passing encoded JSON string literals to JSONField & co.
Per deprecation timeline.
This commit is contained in:
		| @@ -1,9 +1,5 @@ | |||||||
| import json |  | ||||||
| import warnings |  | ||||||
|  |  | ||||||
| from django.contrib.postgres.fields import ArrayField | from django.contrib.postgres.fields import ArrayField | ||||||
| from django.db.models import Aggregate, BooleanField, JSONField, TextField, Value | from django.db.models import Aggregate, BooleanField, JSONField, TextField, Value | ||||||
| from django.utils.deprecation import RemovedInDjango51Warning |  | ||||||
|  |  | ||||||
| from .mixins import OrderableAggMixin | from .mixins import OrderableAggMixin | ||||||
|  |  | ||||||
| @@ -57,35 +53,6 @@ class JSONBAgg(OrderableAggMixin, Aggregate): | |||||||
|     allow_distinct = True |     allow_distinct = True | ||||||
|     output_field = JSONField() |     output_field = JSONField() | ||||||
|  |  | ||||||
|     # RemovedInDjango51Warning: When the deprecation ends, remove __init__(). |  | ||||||
|     def __init__(self, *expressions, default=None, **extra): |  | ||||||
|         super().__init__(*expressions, default=default, **extra) |  | ||||||
|         if ( |  | ||||||
|             isinstance(default, Value) |  | ||||||
|             and isinstance(default.value, str) |  | ||||||
|             and not isinstance(default.output_field, JSONField) |  | ||||||
|         ): |  | ||||||
|             value = default.value |  | ||||||
|             try: |  | ||||||
|                 decoded = json.loads(value) |  | ||||||
|             except json.JSONDecodeError: |  | ||||||
|                 warnings.warn( |  | ||||||
|                     "Passing a Value() with an output_field that isn't a JSONField as " |  | ||||||
|                     "JSONBAgg(default) is deprecated. Pass default=" |  | ||||||
|                     f"Value({value!r}, output_field=JSONField()) instead.", |  | ||||||
|                     stacklevel=2, |  | ||||||
|                     category=RemovedInDjango51Warning, |  | ||||||
|                 ) |  | ||||||
|                 self.default.output_field = self.output_field |  | ||||||
|             else: |  | ||||||
|                 self.default = Value(decoded, self.output_field) |  | ||||||
|                 warnings.warn( |  | ||||||
|                     "Passing an encoded JSON string as JSONBAgg(default) is " |  | ||||||
|                     f"deprecated. Pass default={decoded!r} instead.", |  | ||||||
|                     stacklevel=2, |  | ||||||
|                     category=RemovedInDjango51Warning, |  | ||||||
|                 ) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class StringAgg(OrderableAggMixin, Aggregate): | class StringAgg(OrderableAggMixin, Aggregate): | ||||||
|     function = "STRING_AGG" |     function = "STRING_AGG" | ||||||
|   | |||||||
| @@ -1,5 +1,4 @@ | |||||||
| import json | import json | ||||||
| import warnings |  | ||||||
|  |  | ||||||
| from django import forms | from django import forms | ||||||
| from django.core import checks, exceptions | from django.core import checks, exceptions | ||||||
| @@ -12,7 +11,6 @@ from django.db.models.lookups import ( | |||||||
|     PostgresOperatorLookup, |     PostgresOperatorLookup, | ||||||
|     Transform, |     Transform, | ||||||
| ) | ) | ||||||
| from django.utils.deprecation import RemovedInDjango51Warning |  | ||||||
| from django.utils.translation import gettext_lazy as _ | from django.utils.translation import gettext_lazy as _ | ||||||
|  |  | ||||||
| from . import Field | from . import Field | ||||||
| @@ -101,31 +99,10 @@ class JSONField(CheckFieldDefaultMixin, Field): | |||||||
|     def get_db_prep_value(self, value, connection, prepared=False): |     def get_db_prep_value(self, value, connection, prepared=False): | ||||||
|         if not prepared: |         if not prepared: | ||||||
|             value = self.get_prep_value(value) |             value = self.get_prep_value(value) | ||||||
|         # RemovedInDjango51Warning: When the deprecation ends, replace with: |         if isinstance(value, expressions.Value) and isinstance( | ||||||
|         # if ( |  | ||||||
|         #     isinstance(value, expressions.Value) |  | ||||||
|         #     and isinstance(value.output_field, JSONField) |  | ||||||
|         # ): |  | ||||||
|         #     value = value.value |  | ||||||
|         # elif hasattr(value, "as_sql"): ... |  | ||||||
|         if isinstance(value, expressions.Value): |  | ||||||
|             if isinstance(value.value, str) and not isinstance( |  | ||||||
|             value.output_field, JSONField |             value.output_field, JSONField | ||||||
|         ): |         ): | ||||||
|                 try: |  | ||||||
|                     value = json.loads(value.value, cls=self.decoder) |  | ||||||
|                 except json.JSONDecodeError: |  | ||||||
|             value = value.value |             value = value.value | ||||||
|                 else: |  | ||||||
|                     warnings.warn( |  | ||||||
|                         "Providing an encoded JSON string via Value() is deprecated. " |  | ||||||
|                         f"Use Value({value!r}, output_field=JSONField()) instead.", |  | ||||||
|                         category=RemovedInDjango51Warning, |  | ||||||
|                     ) |  | ||||||
|             elif isinstance(value.output_field, JSONField): |  | ||||||
|                 value = value.value |  | ||||||
|             else: |  | ||||||
|                 return value |  | ||||||
|         elif hasattr(value, "as_sql"): |         elif hasattr(value, "as_sql"): | ||||||
|             return value |             return value | ||||||
|         return connection.ops.adapt_json_value(value, self.encoder) |         return connection.ops.adapt_json_value(value, self.encoder) | ||||||
|   | |||||||
| @@ -274,3 +274,6 @@ to remove usage of these features. | |||||||
| * The ``SimpleTestCase.assertFormsetError()`` method is removed. | * The ``SimpleTestCase.assertFormsetError()`` method is removed. | ||||||
|  |  | ||||||
| * The ``TransactionTestCase.assertQuerysetEqual()`` method is removed. | * The ``TransactionTestCase.assertQuerysetEqual()`` method is removed. | ||||||
|  |  | ||||||
|  | * Support for passing encoded JSON string literals to ``JSONField`` and | ||||||
|  |   associated lookups and expressions is removed. | ||||||
|   | |||||||
| @@ -1085,10 +1085,6 @@ Unless you are sure you wish to work with SQL ``NULL`` values, consider setting | |||||||
|     Storing JSON scalar ``null`` does not violate :attr:`null=False |     Storing JSON scalar ``null`` does not violate :attr:`null=False | ||||||
|     <django.db.models.Field.null>`. |     <django.db.models.Field.null>`. | ||||||
|  |  | ||||||
| .. deprecated:: 4.2 |  | ||||||
|  |  | ||||||
|     Passing ``Value("null")`` to express JSON ``null`` is deprecated. |  | ||||||
|  |  | ||||||
| .. fieldlookup:: jsonfield.key | .. fieldlookup:: jsonfield.key | ||||||
|  |  | ||||||
| Key, index, and path transforms | Key, index, and path transforms | ||||||
|   | |||||||
| @@ -37,7 +37,6 @@ from django.db.models.fields.json import ( | |||||||
| from django.db.models.functions import Cast | from django.db.models.functions import Cast | ||||||
| from django.test import SimpleTestCase, TestCase, skipIfDBFeature, skipUnlessDBFeature | from django.test import SimpleTestCase, TestCase, skipIfDBFeature, skipUnlessDBFeature | ||||||
| from django.test.utils import CaptureQueriesContext | from django.test.utils import CaptureQueriesContext | ||||||
| from django.utils.deprecation import RemovedInDjango51Warning |  | ||||||
|  |  | ||||||
| from .models import CustomJSONDecoder, JSONModel, NullableJSONModel, RelatedJSONModel | from .models import CustomJSONDecoder, JSONModel, NullableJSONModel, RelatedJSONModel | ||||||
|  |  | ||||||
| @@ -216,30 +215,6 @@ class TestSaveLoad(TestCase): | |||||||
|         obj.refresh_from_db() |         obj.refresh_from_db() | ||||||
|         self.assertIsNone(obj.value) |         self.assertIsNone(obj.value) | ||||||
|  |  | ||||||
|     def test_ambiguous_str_value_deprecation(self): |  | ||||||
|         msg = ( |  | ||||||
|             "Providing an encoded JSON string via Value() is deprecated. Use Value([], " |  | ||||||
|             "output_field=JSONField()) instead." |  | ||||||
|         ) |  | ||||||
|         with self.assertWarnsMessage(RemovedInDjango51Warning, msg): |  | ||||||
|             obj = NullableJSONModel.objects.create(value=Value("[]")) |  | ||||||
|         obj.refresh_from_db() |  | ||||||
|         self.assertEqual(obj.value, []) |  | ||||||
|  |  | ||||||
|     @skipUnlessDBFeature("supports_primitives_in_json_field") |  | ||||||
|     def test_value_str_primitives_deprecation(self): |  | ||||||
|         msg = ( |  | ||||||
|             "Providing an encoded JSON string via Value() is deprecated. Use " |  | ||||||
|             "Value(None, output_field=JSONField()) instead." |  | ||||||
|         ) |  | ||||||
|         with self.assertWarnsMessage(RemovedInDjango51Warning, msg): |  | ||||||
|             obj = NullableJSONModel.objects.create(value=Value("null")) |  | ||||||
|         obj.refresh_from_db() |  | ||||||
|         self.assertIsNone(obj.value) |  | ||||||
|         obj = NullableJSONModel.objects.create(value=Value("invalid-json")) |  | ||||||
|         obj.refresh_from_db() |  | ||||||
|         self.assertEqual(obj.value, "invalid-json") |  | ||||||
|  |  | ||||||
|     @skipUnlessDBFeature("supports_primitives_in_json_field") |     @skipUnlessDBFeature("supports_primitives_in_json_field") | ||||||
|     def test_json_null_different_from_sql_null(self): |     def test_json_null_different_from_sql_null(self): | ||||||
|         json_null = NullableJSONModel.objects.create(value=Value(None, JSONField())) |         json_null = NullableJSONModel.objects.create(value=Value(None, JSONField())) | ||||||
|   | |||||||
| @@ -14,9 +14,8 @@ from django.db.models import ( | |||||||
| from django.db.models.fields.json import KeyTextTransform, KeyTransform | from django.db.models.fields.json import KeyTextTransform, KeyTransform | ||||||
| from django.db.models.functions import Cast, Concat, Substr | from django.db.models.functions import Cast, Concat, Substr | ||||||
| from django.test import skipUnlessDBFeature | from django.test import skipUnlessDBFeature | ||||||
| from django.test.utils import Approximate, ignore_warnings | from django.test.utils import Approximate | ||||||
| from django.utils import timezone | from django.utils import timezone | ||||||
| from django.utils.deprecation import RemovedInDjango51Warning |  | ||||||
|  |  | ||||||
| from . import PostgreSQLTestCase | from . import PostgreSQLTestCase | ||||||
| from .models import AggregateTestModel, HotelReservation, Room, StatTestModel | from .models import AggregateTestModel, HotelReservation, Room, StatTestModel | ||||||
| @@ -152,59 +151,6 @@ class TestGeneralAggregate(PostgreSQLTestCase): | |||||||
|                     ) |                     ) | ||||||
|                     self.assertEqual(values, {"aggregation": expected_result}) |                     self.assertEqual(values, {"aggregation": expected_result}) | ||||||
|  |  | ||||||
|     @ignore_warnings(category=RemovedInDjango51Warning) |  | ||||||
|     def test_jsonb_agg_default_str_value(self): |  | ||||||
|         AggregateTestModel.objects.all().delete() |  | ||||||
|         queryset = AggregateTestModel.objects.all() |  | ||||||
|         self.assertEqual( |  | ||||||
|             queryset.aggregate( |  | ||||||
|                 aggregation=JSONBAgg("integer_field", default=Value("<empty>")) |  | ||||||
|             ), |  | ||||||
|             {"aggregation": "<empty>"}, |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     def test_jsonb_agg_default_str_value_deprecation(self): |  | ||||||
|         queryset = AggregateTestModel.objects.all() |  | ||||||
|         msg = ( |  | ||||||
|             "Passing a Value() with an output_field that isn't a JSONField as " |  | ||||||
|             "JSONBAgg(default) is deprecated. Pass default=Value('<empty>', " |  | ||||||
|             "output_field=JSONField()) instead." |  | ||||||
|         ) |  | ||||||
|         with self.assertWarnsMessage(RemovedInDjango51Warning, msg): |  | ||||||
|             queryset.aggregate( |  | ||||||
|                 aggregation=JSONBAgg("integer_field", default=Value("<empty>")) |  | ||||||
|             ) |  | ||||||
|         with self.assertWarnsMessage(RemovedInDjango51Warning, msg): |  | ||||||
|             queryset.none().aggregate( |  | ||||||
|                 aggregation=JSONBAgg("integer_field", default=Value("<empty>")) |  | ||||||
|             ), |  | ||||||
|  |  | ||||||
|     @ignore_warnings(category=RemovedInDjango51Warning) |  | ||||||
|     def test_jsonb_agg_default_encoded_json_string(self): |  | ||||||
|         AggregateTestModel.objects.all().delete() |  | ||||||
|         queryset = AggregateTestModel.objects.all() |  | ||||||
|         self.assertEqual( |  | ||||||
|             queryset.aggregate( |  | ||||||
|                 aggregation=JSONBAgg("integer_field", default=Value("[]")) |  | ||||||
|             ), |  | ||||||
|             {"aggregation": []}, |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     def test_jsonb_agg_default_encoded_json_string_deprecation(self): |  | ||||||
|         queryset = AggregateTestModel.objects.all() |  | ||||||
|         msg = ( |  | ||||||
|             "Passing an encoded JSON string as JSONBAgg(default) is deprecated. Pass " |  | ||||||
|             "default=[] instead." |  | ||||||
|         ) |  | ||||||
|         with self.assertWarnsMessage(RemovedInDjango51Warning, msg): |  | ||||||
|             queryset.aggregate( |  | ||||||
|                 aggregation=JSONBAgg("integer_field", default=Value("[]")) |  | ||||||
|             ) |  | ||||||
|         with self.assertWarnsMessage(RemovedInDjango51Warning, msg): |  | ||||||
|             queryset.none().aggregate( |  | ||||||
|                 aggregation=JSONBAgg("integer_field", default=Value("[]")) |  | ||||||
|             ) |  | ||||||
|  |  | ||||||
|     def test_array_agg_charfield(self): |     def test_array_agg_charfield(self): | ||||||
|         values = AggregateTestModel.objects.aggregate(arrayagg=ArrayAgg("char_field")) |         values = AggregateTestModel.objects.aggregate(arrayagg=ArrayAgg("char_field")) | ||||||
|         self.assertEqual(values, {"arrayagg": ["Foo1", "Foo2", "Foo4", "Foo3"]}) |         self.assertEqual(values, {"arrayagg": ["Foo1", "Foo2", "Foo4", "Foo3"]}) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user