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):
|
||||
if not prepared:
|
||||
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)
|
||||
|
||||
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:
|
||||
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):
|
||||
transform = super().get_transform(name)
|
||||
|
@ -430,6 +430,17 @@ class RelatedJSONModel(models.Model):
|
||||
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):
|
||||
big_integer = models.BigIntegerField()
|
||||
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.utils import CaptureQueriesContext
|
||||
|
||||
from .models import CustomJSONDecoder, JSONModel, NullableJSONModel, RelatedJSONModel
|
||||
from .models import (
|
||||
CustomJSONDecoder,
|
||||
CustomSerializationJSONModel,
|
||||
JSONModel,
|
||||
NullableJSONModel,
|
||||
RelatedJSONModel,
|
||||
)
|
||||
|
||||
|
||||
@skipUnlessDBFeature("supports_json_field")
|
||||
@ -298,6 +304,17 @@ class TestSaveLoad(TestCase):
|
||||
obj.refresh_from_db()
|
||||
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")
|
||||
class TestQuerying(TestCase):
|
||||
|
Loading…
x
Reference in New Issue
Block a user