From 9525135698bd4f97cf1431776ef52ae393dfb3c0 Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Sun, 16 Feb 2025 21:35:12 -0500 Subject: [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 Backport of 0bf412111be686b6b23e00863f5d449d63557dbf from main. --- django/db/models/fields/json.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'django/db/models/fields/json.py') diff --git a/django/db/models/fields/json.py b/django/db/models/fields/json.py index 8d743c436a..188fcf520c 100644 --- a/django/db/models/fields/json.py +++ b/django/db/models/fields/json.py @@ -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) -- cgit v1.3