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:
parent
69af3bea99
commit
5e4c1793b7
@ -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"]})
|
||||||
|
Loading…
Reference in New Issue
Block a user