diff --git a/django/db/models/fields/json.py b/django/db/models/fields/json.py index 71c3f4d335..cf4f5953a7 100644 --- a/django/db/models/fields/json.py +++ b/django/db/models/fields/json.py @@ -665,7 +665,19 @@ class KeyTransformExact(JSONExact): class KeyTransformIExact( CaseInsensitiveMixin, KeyTransformTextLookupMixin, lookups.IExact ): - pass + can_use_none_as_rhs = True + + def as_sql(self, compiler, connection): + if self.rhs is None: + # Interpret __iexact=None on KeyTextTransform as __exact=None on + # KeyTransform. + keytransform = KeyTransform(self.lhs.key_name, self.lhs.lhs) + exact_lookup = keytransform.get_lookup("exact")(keytransform, self.rhs) + # Delegate to the backend vendor method, if it exists. + vendor = connection.vendor + as_vendor = getattr(exact_lookup, f"as_{vendor}", exact_lookup.as_sql) + return as_vendor(compiler, connection) + return super().as_sql(compiler, connection) class KeyTransformIContains( diff --git a/docs/releases/6.1.txt b/docs/releases/6.1.txt index 2e6e7235d7..c4ecefc08a 100644 --- a/docs/releases/6.1.txt +++ b/docs/releases/6.1.txt @@ -400,6 +400,11 @@ Miscellaneous * The minimum supported version of SQLite is increased from 3.31.0 to 3.37.0. +* The :lookup:`iexact=None ` lookup on + :class:`~django.db.models.JSONField` key transforms now matches JSON + ``null``, to match the behavior of :lookup:`exact=None ` on key + transforms. Previously, it was interpreted as an :lookup:`isnull` lookup. + .. _deprecated-features-6.1: Features deprecated in 6.1 diff --git a/tests/model_fields/test_jsonfield.py b/tests/model_fields/test_jsonfield.py index 76cdc0e421..1afeef31eb 100644 --- a/tests/model_fields/test_jsonfield.py +++ b/tests/model_fields/test_jsonfield.py @@ -782,6 +782,12 @@ class TestQuerying(TestCase): [self.objs[4]], ) + def test_key_iexact_none(self): + self.assertSequenceEqual( + NullableJSONModel.objects.filter(value__j__iexact=None), + [self.objs[4]], + ) + def test_none_key_exclude(self): obj = NullableJSONModel.objects.create(value={"j": 1}) if connection.vendor == "oracle":