1
1
from bson import ObjectId , errors
2
2
from django .core import exceptions
3
+ from django .db import NotSupportedError
3
4
from django .db .models import JSONField
4
5
from django .db .models .fields import AutoField , Field
5
6
from django .db .models .fields .json import (
11
12
HasKeys ,
12
13
JSONExact ,
13
14
KeyTransform ,
15
+ KeyTransformIn ,
16
+ KeyTransformIsNull ,
14
17
)
15
18
from django .utils .translation import gettext_lazy as _
16
19
@@ -59,8 +62,14 @@ def from_db_value(self, value, expression, connection):
59
62
)
60
63
61
64
62
- def process_rhs (node , compiler , connection ):
65
+ def json_process_rhs (node , compiler , connection ):
63
66
_ , value = node .process_rhs (compiler , connection )
67
+
68
+ # Django's framework transform the [None] into a [null],
69
+ # we have to revertit.
70
+ if value == ["null" ]:
71
+ value = [None ]
72
+
64
73
lookup_name = node .lookup_name
65
74
if lookup_name not in ("in" , "range" ):
66
75
value = value [0 ] if len (value ) > 0 else []
@@ -78,41 +87,33 @@ def key_transform(self, compiler, connection):
78
87
return "." .join ([lhs_mql , * key_transforms ])
79
88
80
89
81
- def data_contains (self , compiler , connection ):
82
- lhs_mql = process_lhs (self , compiler , connection )
83
- value = process_rhs (self , compiler , connection )
84
- if not value :
85
- return {lhs_mql : {"$type" : "array" }}
86
- if isinstance (value , list ):
87
- return {"$and" : [{lhs_mql : v } for v in value ]}
88
- if isinstance (value , dict ):
89
- return {"$and" : [{f"{ lhs_mql } .{ k } " : v } for k , v in value .items ()]}
90
- return {lhs_mql : value }
90
+ def data_contains (self , compiler , connection ): # noqa: ARG001
91
+ raise NotSupportedError ("contains lookup is not supported on this database backend." )
92
+
93
+
94
+ def contained_by (self , compiler , connection ): # noqa: ARG001
95
+ raise NotSupportedError ("contained_by lookup is not supported on this database backend." )
91
96
92
97
93
98
def json_exact (self , compiler , connection ):
99
+ rhs_mql = json_process_rhs (self , compiler , connection )
100
+ lhs_mql = process_lhs (self , compiler , connection )
101
+ return {lhs_mql : {"$eq" : rhs_mql , "$exists" : True }}
102
+
103
+
104
+ def key_transform_isnull (self , compiler , connection ):
94
105
lhs_mql = process_lhs (self , compiler , connection )
95
- rhs_mql = process_rhs (self , compiler , connection )
96
- return {lhs_mql : {"$eq" : rhs_mql }}
106
+ 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 }}]}
97
110
98
111
99
- def contained_by (self , compiler , connection ):
112
+ def key_transform_in (self , compiler , connection ):
100
113
lhs_mql = process_lhs (self , compiler , connection )
101
- value = process_rhs (self , compiler , connection )
102
- if isinstance (value , list ):
103
- if not value :
104
- return {lhs_mql : []}
105
- return {"$and" : [{"$or" : [{lhs_mql : v }, {lhs_mql : {"$exists" : False }}]} for v in value ]}
106
- if isinstance (value , dict ):
107
- if not value :
108
- return {lhs_mql : {}}
109
- return {
110
- "$and" : [
111
- {"$or" : [{f"{ lhs_mql } .{ k } " : v }, {f"{ lhs_mql } .{ k } " : {"$exists" : False }}]}
112
- for k , v in value .items ()
113
- ]
114
- }
115
- return {lhs_mql : value }
114
+ value = json_process_rhs (self , compiler , connection )
115
+ rhs_mql = connection .operators [self .lookup_name ](value )
116
+ return {lhs_mql : rhs_mql }
116
117
117
118
118
119
def has_key_lookup (self , compiler , connection ):
@@ -124,9 +125,7 @@ def has_key_lookup(self, compiler, connection):
124
125
for key in rhs :
125
126
if isinstance (key , KeyTransform ):
126
127
* _ , rhs_key_transforms = key .preprocess_lhs (compiler , connection )
127
- rhs_key_transforms = "." .join (
128
- rhs_key_transforms
129
- ) # process_lhs(key, compiler, connection)
128
+ rhs_key_transforms = "." .join (rhs_key_transforms )
130
129
else :
131
130
rhs_key_transforms = str (key )
132
131
rhs_json_path = f"{ lhs } .{ rhs_key_transforms } "
@@ -151,3 +150,5 @@ def load_fields():
151
150
HasAnyKeys .mongo_operator = "$or"
152
151
HasKey .mongo_operator = None
153
152
HasKeys .mongo_operator = "$and"
153
+ KeyTransformIsNull .as_mql = key_transform_isnull
154
+ KeyTransformIn .as_mql = key_transform_in
0 commit comments