1
0
mirror of https://github.com/django/django.git synced 2024-12-31 21:46:05 +00:00

Refs #33308 -- Removed support for passing encoded JSON string literals to JSONField & co.

Per deprecation timeline.
This commit is contained in:
Mariusz Felisiak 2023-09-14 16:03:52 +02:00
parent 69af3bea99
commit 5e4c1793b7
6 changed files with 8 additions and 144 deletions

View File

@ -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"

View File

@ -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)

View File

@ -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.

View File

@ -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

View File

@ -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()))

View File

@ -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"]})