@@ -42,6 +42,10 @@ def _extract_comparison(cls, args):
42
42
def _get_value (obj ):
43
43
while isinstance (obj , Tree ):
44
44
obj = obj .children [0 ]
45
+
46
+ if isinstance (obj , Q ):
47
+ return obj
48
+
45
49
return obj .value
46
50
47
51
def sign_prop (self , args ):
@@ -72,13 +76,47 @@ class RQLToDjangoORMTransformer(BaseRQLTransformer):
72
76
They are applied later in FilterCls. This is done on purpose, because transformer knows
73
77
nothing about the mappings between filter names and orm fields.
74
78
"""
79
+ NAMESPACE_PROVIDERS = ('comp' , 'listing' )
80
+ NAMESPACE_FILLERS = ('prop' ,)
81
+ NAMESPACE_ACTIVATORS = ('tuple' ,)
82
+
75
83
def __init__ (self , filter_cls_instance ):
76
84
self ._filter_cls_instance = filter_cls_instance
77
85
78
86
self ._ordering = []
79
87
self ._select = []
80
88
self ._filtered_props = set ()
81
89
90
+ self ._namespace = []
91
+ self ._active_namespace = 0
92
+
93
+ self .__visit_tokens__ = False
94
+
95
+ def _push_namespace (self , tree ):
96
+ if tree .data in self .NAMESPACE_PROVIDERS :
97
+ self ._namespace .append (None )
98
+ elif tree .data in self .NAMESPACE_ACTIVATORS :
99
+ self ._active_namespace = len (self ._namespace )
100
+ elif (tree .data in self .NAMESPACE_FILLERS
101
+ and self ._namespace
102
+ and self ._namespace [- 1 ] is None ):
103
+ self ._namespace [- 1 ] = self ._get_value (tree )
104
+
105
+ def _pop_namespace (self , tree ):
106
+ if tree .data in self .NAMESPACE_PROVIDERS :
107
+ self ._namespace .pop ()
108
+ elif tree .data in self .NAMESPACE_ACTIVATORS :
109
+ self ._active_namespace -= 1
110
+
111
+ def _get_current_namespace (self ):
112
+ return self ._namespace [:self ._active_namespace ]
113
+
114
+ def _transform_tree (self , tree ):
115
+ self ._push_namespace (tree )
116
+ ret_value = super ()._transform_tree (tree )
117
+ self ._pop_namespace (tree )
118
+ return ret_value
119
+
82
120
@property
83
121
def ordering_filters (self ):
84
122
return self ._ordering
@@ -94,9 +132,19 @@ def start(self, args):
94
132
95
133
def comp (self , args ):
96
134
prop , operation , value = self ._extract_comparison (args )
97
- self ._filtered_props .add (prop )
98
135
99
- return self ._filter_cls_instance .build_q_for_filter (FilterArgs (prop , operation , value ))
136
+ if isinstance (value , Q ):
137
+ if operation == ComparisonOperators .EQ :
138
+ return value
139
+ else :
140
+ return ~ value
141
+
142
+ filter_args = FilterArgs (prop , operation , value , namespace = self ._get_current_namespace ())
143
+ self ._filtered_props .add (filter_args .filter_name )
144
+ return self ._filter_cls_instance .build_q_for_filter (filter_args )
145
+
146
+ def tuple (self , args ):
147
+ return Q (* args )
100
148
101
149
def logical (self , args ):
102
150
operation = args [0 ].data
@@ -119,10 +167,17 @@ def listing(self, args):
119
167
120
168
q = Q ()
121
169
for value_tree in args [2 :]:
122
- field_q = self ._filter_cls_instance .build_q_for_filter (FilterArgs (
123
- prop , f_op , self ._get_value (value_tree ),
124
- list_operator = operation ,
125
- ))
170
+ value = self ._get_value (value_tree )
171
+ if isinstance (value , Q ):
172
+ if f_op == ComparisonOperators .EQ :
173
+ field_q = value
174
+ else :
175
+ field_q = ~ value
176
+ else :
177
+ field_q = self ._filter_cls_instance .build_q_for_filter (FilterArgs (
178
+ prop , f_op , value ,
179
+ list_operator = operation ,
180
+ ))
126
181
if operation == ListOperators .IN :
127
182
q |= field_q
128
183
else :
@@ -135,9 +190,9 @@ def listing(self, args):
135
190
def searching (self , args ):
136
191
# like, ilike
137
192
operation , prop , val = tuple (self ._get_value (args [index ]) for index in range (3 ))
138
- self ._filtered_props . add ( prop )
139
-
140
- return self ._filter_cls_instance .build_q_for_filter (FilterArgs ( prop , operation , val ) )
193
+ filter_args = FilterArgs ( prop , operation , val , namespace = self ._get_current_namespace () )
194
+ self . _filtered_props . add ( filter_args . filter_name )
195
+ return self ._filter_cls_instance .build_q_for_filter (filter_args )
141
196
142
197
def ordering (self , args ):
143
198
props = args [1 :]
0 commit comments