@@ -83,57 +83,67 @@ def setUpTestData(cls):
8383 )
8484
8585 cls .null_objs = NullableJSONModel .objects .bulk_create (NullableJSONModel () for _ in range (5 ))
86- cls .null_objs .append (NullableJSONModel .objects .create (value = {"name" : None }))
8786 cls .unique_id = ObjectId ()
87+ for model in (Book , NullableJSONModel ):
88+ collection = connection .database .get_collection (model ._meta .db_table )
89+ collection .insert_one ({"_id" : cls .unique_id })
8890
89- def _test_none_filter_nullable_json (self , op , predicate , field ):
91+ def test_none_filter_nullable_json_exact (self ):
9092 with self .assertNumQueries (1 ) as ctx :
9193 self .assertQuerySetEqual (
92- NullableJSONModel .objects .filter (
93- ** {f"{ field } __{ op } " : [None ] if op == "in" else None }
94- ),
95- [],
94+ NullableJSONModel .objects .filter (value = None ),
95+ self .null_objs [:- 1 ],
9696 )
9797 self .assertAggregateQuery (
9898 ctx .captured_queries [0 ]["sql" ],
9999 "lookup__nullablejsonmodel" ,
100- [{"$match" : {"$and" : [{"$exists" : False }, predicate ( field ) ]}}],
100+ [{"$match" : {"$and" : [{"value" : { " $exists" : True }}, { "value" : None } ]}}],
101101 )
102102
103- def _test_none_filter_binary_operator (self , op , predicate , field ):
103+ def test_none_filter_nullable_json_in (self ):
104104 with self .assertNumQueries (1 ) as ctx :
105105 self .assertQuerySetEqual (
106- Book .objects .filter (** {f"{ field } __{ op } " : [None ] if op == "in" else None }), []
106+ NullableJSONModel .objects .filter (value__in = [None ]),
107+ self .null_objs [:- 1 ],
107108 )
109+ self .assertAggregateQuery (
110+ ctx .captured_queries [0 ]["sql" ],
111+ "lookup__nullablejsonmodel" ,
112+ [{"$match" : {"$and" : [{"value" : {"$exists" : True }}, {"value" : {"$in" : [None ]}}]}}],
113+ )
114+
115+ def test_none_filter_binary_operator_exact (self ):
116+ with self .assertNumQueries (1 ) as ctx :
117+ self .assertQuerySetEqual (Book .objects .filter (title = None ), [])
108118 self .assertAggregateQuery (
109119 ctx .captured_queries [0 ]["sql" ],
110120 "lookup__book" ,
111121 [
112122 {
113123 "$match" : {
114124 "$or" : [
115- {"$and" : [{field : {"$exists" : True }}, predicate ( field ) ]},
116- {"$expr" : {"$eq" : [{"$type" : f"$ { field } " }, "missing" ]}},
125+ {"$and" : [{"title" : {"$exists" : True }}, { "title" : None } ]},
126+ {"$expr" : {"$eq" : [{"$type" : "$title " }, "missing" ]}},
117127 ]
118128 }
119129 }
120130 ],
121131 )
122132
123- def _test_with_raw_data (self , model , test_function , field ):
124- collection = connection . database . get_collection ( model . _meta . db_table )
125- try :
126- collection . insert_one ({ "_id" : self .unique_id })
127-
128- for op , predicate in self . _OPERATOR_PREDICATE_MAP . items ():
129- with self . subTest ( op = op ):
130- test_function ( op , predicate , field )
131-
132- finally :
133- collection . delete_one ({ "_id " : self . unique_id })
134-
135- def test_none_filter_nullable_json ( self ):
136- self . _test_with_raw_data ( NullableJSONModel , self . _test_none_filter_nullable_json , "value" )
137-
138- def test_none_filter_binary_operator ( self ):
139- self . _test_with_raw_data ( Book , self . _test_none_filter_binary_operator , "title" )
133+ def test_none_filter_binary_operator_in (self ):
134+ with self . assertNumQueries ( 1 ) as ctx :
135+ self . assertQuerySetEqual ( Book . objects . filter ( title__in = [ None ]), [])
136+ self .assertAggregateQuery (
137+ ctx . captured_queries [ 0 ][ "sql" ],
138+ "lookup__book" ,
139+ [
140+ {
141+ "$match" : {
142+ "$or" : [
143+ { "$and " : [{ "title" : { "$exists" : True }}, { "title" : None }]},
144+ { "$expr" : { "$eq" : [{ "$type" : "$title" }, "missing" ]}},
145+ ]
146+ }
147+ }
148+ ],
149+ )
0 commit comments