@@ -129,13 +129,15 @@ def query(_doc_cls=None, **kwargs):
129
129
130
130
singular_ops = [None , "ne" , "gt" , "gte" , "lt" , "lte" , "not" ]
131
131
singular_ops += STRING_OPERATORS
132
+ is_iterable = False
132
133
if op in singular_ops :
133
134
value = field .prepare_query_value (op , value )
134
135
135
136
if isinstance (field , CachedReferenceField ) and value :
136
137
value = value ["_id" ]
137
138
138
139
elif op in ("in" , "nin" , "all" , "near" ) and not isinstance (value , dict ):
140
+ is_iterable = True
139
141
# Raise an error if the in/nin/all/near param is not iterable.
140
142
value = _prepare_query_for_iterable (field , op , value )
141
143
@@ -144,10 +146,24 @@ def query(_doc_cls=None, **kwargs):
144
146
# * If the value is a DBRef, the key should be "field_name._ref".
145
147
# * If the value is an ObjectId, the key should be "field_name._ref.$id".
146
148
if isinstance (field , GenericReferenceField ):
147
- if isinstance (value , DBRef ):
149
+ if isinstance (value , DBRef ) or (
150
+ is_iterable and all (isinstance (v , DBRef ) for v in value )
151
+ ):
148
152
parts [- 1 ] += "._ref"
149
- elif isinstance (value , ObjectId ):
153
+ elif isinstance (value , ObjectId ) or (
154
+ is_iterable and all (isinstance (v , ObjectId ) for v in value )
155
+ ):
150
156
parts [- 1 ] += "._ref.$id"
157
+ elif (
158
+ is_iterable
159
+ and any (isinstance (v , DBRef ) for v in value )
160
+ and any (isinstance (v , ObjectId ) for v in value )
161
+ ):
162
+ raise ValueError (
163
+ "The `in`, `nin`, `all`, or `near`-operators cannot "
164
+ "be applied to mixed queries of DBRef/ObjectId/%s"
165
+ % _doc_cls .__name__
166
+ )
151
167
152
168
# if op and op not in COMPARISON_OPERATORS:
153
169
if op :
0 commit comments