Skip to content

Commit 18eb7da

Browse files
committed
Handle F keystransform.
1 parent a3c6bbc commit 18eb7da

File tree

3 files changed

+35
-12
lines changed

3 files changed

+35
-12
lines changed

django_mongodb/features.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,8 @@ def django_test_expected_failures(self):
409409
"model_fields.test_jsonfield.JSONFieldTests.test_db_check_constraints",
410410
},
411411
"Mongodb's Null behaviour is different from sql's": {
412-
"model_fields.test_jsonfield.TestQuerying.test_none_key_exclude",
413-
"model_fields.test_jsonfield.TestQuerying.test_isnull_key",
412+
"model_fields.test_jsonfield.TestQuerying.test_none_key_and_exact_lookup",
413+
# "model_fields.test_jsonfield.TestQuerying.test_isnull_key",
414414
},
415415
"Pipeline filtering": {"model_fields.test_jsonfield.TestQuerying.test_icontains"},
416416
}

django_mongodb/fields/auto.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,15 @@ def from_db_value(self, value, expression, connection):
6565
def json_process_rhs(node, compiler, connection):
6666
_, value = node.process_rhs(compiler, connection)
6767

68-
# Django's framework transform the [None] into a [null],
69-
# we have to revertit.
70-
if value == ["null"]:
71-
value = [None]
72-
7368
lookup_name = node.lookup_name
7469
if lookup_name not in ("in", "range"):
7570
value = value[0] if len(value) > 0 else []
71+
else:
72+
result_value = []
73+
for ind, elem in enumerate(node.rhs):
74+
item = f"${value[ind]}" if isinstance(elem, KeyTransform) else value[ind]
75+
result_value.append(item)
76+
value = result_value
7677

7778
return value
7879

@@ -96,24 +97,31 @@ def contained_by(self, compiler, connection): # noqa: ARG001
9697

9798

9899
def json_exact(self, compiler, connection):
99-
rhs_mql = json_process_rhs(self, compiler, connection)
100100
lhs_mql = process_lhs(self, compiler, connection)
101+
rhs_mql = json_process_rhs(self, compiler, connection)
102+
if rhs_mql == "null":
103+
return {"$or": [{lhs_mql: {"$eq": None}}, {lhs_mql: {"$exists": False}}]}
104+
# return {lhs_mql: {"$eq": None, "$exists": True}}
105+
# return key_transform_isnull(self, compiler, connection)
101106
return {lhs_mql: {"$eq": rhs_mql, "$exists": True}}
102107

103108

104109
def key_transform_isnull(self, compiler, connection):
105110
lhs_mql = process_lhs(self, compiler, connection)
106111
rhs_mql = json_process_rhs(self, compiler, connection)
107-
if rhs_mql is False:
108-
return {lhs_mql: {"$neq": None}}
109-
return {"$or": [{lhs_mql: {"$eq": None}}, {lhs_mql: {"$exists": False}}]}
112+
# if rhs_mql is False:
113+
# return {lhs_mql: {"$neq": None}}
114+
# return {"$or": [{lhs_mql: {"$eq": None}}, {lhs_mql: {"$exists": False}}]}
115+
116+
# https://code.djangoproject.com/ticket/32252
117+
return {lhs_mql: {"$exists": not rhs_mql}}
110118

111119

112120
def key_transform_in(self, compiler, connection):
113121
lhs_mql = process_lhs(self, compiler, connection)
114122
value = json_process_rhs(self, compiler, connection)
115123
rhs_mql = connection.operators[self.lookup_name](value)
116-
return {lhs_mql: rhs_mql}
124+
return {"$expr": {lhs_mql: rhs_mql}}
117125

118126

119127
def has_key_lookup(self, compiler, connection):

django_mongodb/lookups.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,24 @@ def uuid_text_mixin(self, compiler, connection): # noqa: ARG001
4646
raise NotSupportedError("Pattern lookups on UUIDField are not supported.")
4747

4848

49+
_resolve_expression_parameter = FieldGetDbPrepValueIterableMixin.resolve_expression_parameter
50+
51+
52+
def resolve_expression_parameter(self, compiler, connection, sql, param):
53+
if connection.vendor == "mongodb":
54+
params = [param]
55+
if hasattr(param, "resolve_expression"):
56+
param = param.resolve_expression(compiler.query)
57+
if hasattr(param, "as_mql"):
58+
params = [param.as_mql(compiler, connection)]
59+
return "", params
60+
return _resolve_expression_parameter(self, compiler, connection, sql, param)
61+
62+
4963
def register_lookups():
5064
BuiltinLookup.as_mql = builtin_lookup
5165
In.as_mql = RelatedIn.as_mql = in_
5266
IsNull.as_mql = is_null
5367
PatternLookup.prep_lookup_value_mongo = pattern_lookup_prep_lookup_value
5468
UUIDTextMixin.as_mql = uuid_text_mixin
69+
FieldGetDbPrepValueIterableMixin.resolve_expression_parameter = resolve_expression_parameter

0 commit comments

Comments
 (0)