mirror of
https://github.com/django/django.git
synced 2025-03-06 07:22:32 +00:00
[5.2.x] Fixed #35167 -- Delegated to super() in JSONField.get_db_prep_save().
Avoids reports of bulk_update() sending Cast expressions to JSONField.get_prep_value(). Co-authored-by: Simon Charette <charette.s@gmail.com> Backport of 0bf412111be686b6b23e00863f5d449d63557dbf from main.
This commit is contained in:
parent
bb4f65ec87
commit
9525135698
@ -99,18 +99,23 @@ 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)
|
||||||
if isinstance(value, expressions.Value) and isinstance(
|
|
||||||
value.output_field, JSONField
|
|
||||||
):
|
|
||||||
value = value.value
|
|
||||||
elif hasattr(value, "as_sql"):
|
|
||||||
return value
|
|
||||||
return connection.ops.adapt_json_value(value, self.encoder)
|
return connection.ops.adapt_json_value(value, self.encoder)
|
||||||
|
|
||||||
def get_db_prep_save(self, value, connection):
|
def get_db_prep_save(self, value, connection):
|
||||||
|
# This slightly involved logic is to allow for `None` to be used to
|
||||||
|
# store SQL `NULL` while `Value(None, JSONField())` can be used to
|
||||||
|
# store JSON `null` while preventing compilable `as_sql` values from
|
||||||
|
# making their way to `get_db_prep_value`, which is what the `super()`
|
||||||
|
# implementation does.
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
return value
|
||||||
return self.get_db_prep_value(value, connection)
|
if (
|
||||||
|
isinstance(value, expressions.Value)
|
||||||
|
and value.value is None
|
||||||
|
and isinstance(value.output_field, JSONField)
|
||||||
|
):
|
||||||
|
value = None
|
||||||
|
return super().get_db_prep_save(value, connection)
|
||||||
|
|
||||||
def get_transform(self, name):
|
def get_transform(self, name):
|
||||||
transform = super().get_transform(name)
|
transform = super().get_transform(name)
|
||||||
|
@ -430,6 +430,17 @@ class RelatedJSONModel(models.Model):
|
|||||||
required_db_features = {"supports_json_field"}
|
required_db_features = {"supports_json_field"}
|
||||||
|
|
||||||
|
|
||||||
|
class CustomSerializationJSONModel(models.Model):
|
||||||
|
class StringifiedJSONField(models.JSONField):
|
||||||
|
def get_prep_value(self, value):
|
||||||
|
return json.dumps(value, cls=self.encoder)
|
||||||
|
|
||||||
|
json_field = StringifiedJSONField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
required_db_features = {"supports_json_field"}
|
||||||
|
|
||||||
|
|
||||||
class AllFieldsModel(models.Model):
|
class AllFieldsModel(models.Model):
|
||||||
big_integer = models.BigIntegerField()
|
big_integer = models.BigIntegerField()
|
||||||
binary = models.BinaryField()
|
binary = models.BinaryField()
|
||||||
|
@ -40,7 +40,13 @@ 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 .models import CustomJSONDecoder, JSONModel, NullableJSONModel, RelatedJSONModel
|
from .models import (
|
||||||
|
CustomJSONDecoder,
|
||||||
|
CustomSerializationJSONModel,
|
||||||
|
JSONModel,
|
||||||
|
NullableJSONModel,
|
||||||
|
RelatedJSONModel,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@skipUnlessDBFeature("supports_json_field")
|
@skipUnlessDBFeature("supports_json_field")
|
||||||
@ -298,6 +304,17 @@ class TestSaveLoad(TestCase):
|
|||||||
obj.refresh_from_db()
|
obj.refresh_from_db()
|
||||||
self.assertEqual(obj.value, value)
|
self.assertEqual(obj.value, value)
|
||||||
|
|
||||||
|
def test_bulk_update_custom_get_prep_value(self):
|
||||||
|
objs = CustomSerializationJSONModel.objects.bulk_create(
|
||||||
|
[CustomSerializationJSONModel(pk=1, json_field={"version": "1"})]
|
||||||
|
)
|
||||||
|
objs[0].json_field["version"] = "1-alpha"
|
||||||
|
CustomSerializationJSONModel.objects.bulk_update(objs, ["json_field"])
|
||||||
|
self.assertSequenceEqual(
|
||||||
|
CustomSerializationJSONModel.objects.values("json_field"),
|
||||||
|
[{"json_field": '{"version": "1-alpha"}'}],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@skipUnlessDBFeature("supports_json_field")
|
@skipUnlessDBFeature("supports_json_field")
|
||||||
class TestQuerying(TestCase):
|
class TestQuerying(TestCase):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user