#35167: JSONFIeld get_db_prep_value being called with `Cast` types
---------------------------------+------------------------------------
Reporter: Samantha Hughes | Owner: (none)
Type: Bug | Status: new
Component: Error reporting | Version: 4.2
Severity: Normal | Resolution:
Keywords: JSONField | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+------------------------------------
Comment (by Simon Charette):
You mentioned that you are using Django 4.2 so the following patch won't
apply cleanly against your branch but against main it gets the tests
passing
{{{#!diff
diff --git a/django/db/models/fields/json.py
b/django/db/models/fields/json.py
index 571e6e79f3..73b4a4dd50 100644
--- a/django/db/models/fields/json.py
+++ b/django/db/models/fields/json.py
@@ -99,18 +99,23 @@ def get_internal_type(self):
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 convoluted 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)
+ elif (
+ 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)
}}}
Basically now that the deprecation shims have been removed the logic can
be slightly simplified to only have to special case the `Value(None,
JSONField())` which is truly the only problematic case in the
implementation of `JSONField` due to ambiguous nature of `None` with
regards to SQL `NULL` and JSON `null`.
--
Ticket URL: <https://code.djangoproject.com/ticket/35167#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/0107018d7c9d2f39-246340ce-af48-4156-a2df-f60361f10c90-000000%40eu-central-1.amazonses.com.