11#coding=utf-8
2- from uliweb import expose , functions , models
2+ from uliweb import expose , functions , models , UliwebError
33from uliweb .orm import ModelNotFound
4+ from sqlalchemy .sql import and_ , or_ , not_
45from json import loads
56import logging
67import traceback
@@ -50,22 +51,22 @@ def get(self):
5051 return json (self .rdict )
5152
5253 def _get_one (self ,key ):
53- modelname = key
54+ model_name = key
5455 params = self .request_data [key ]
5556 params_role = params .get ("@role" )
5657
5758 try :
58- model = getattr (models ,modelname )
59- model_setting = settings .APIJSON_MODELS .get (modelname ,{})
59+ model = getattr (models ,model_name )
60+ model_setting = settings .APIJSON_MODELS .get (model_name ,{})
6061 except ModelNotFound as e :
61- log .error ("try to find model '%s' but not found: '%s'" % (modelname ,e ))
62- return json ({"code" :400 ,"msg" :"model '%s' not found" % (modelname )})
62+ log .error ("try to find model '%s' but not found: '%s'" % (model_name ,e ))
63+ return json ({"code" :400 ,"msg" :"model '%s' not found" % (model_name )})
6364 model_column_set = None
6465 q = model .all ()
6566
6667 GET = model_setting .get ("GET" )
6768 if not GET :
68- return json ({"code" :400 ,"msg" :"'%s' not accessible" % (modelname )})
69+ return json ({"code" :400 ,"msg" :"'%s' not accessible" % (model_name )})
6970
7071 roles = GET .get ("roles" )
7172 permission_check_ok = False
@@ -75,7 +76,7 @@ def _get_one(self,key):
7576 else :
7677 params_role = "UNKNOWN"
7778 if params_role not in roles :
78- return json ({"code" :400 ,"msg" :"'%s' not accessible by role '%s'" % (modelname ,params_role )})
79+ return json ({"code" :400 ,"msg" :"'%s' not accessible by role '%s'" % (model_name ,params_role )})
7980 if params_role == "UNKNOWN" :
8081 permission_check_ok = True
8182 elif functions .has_role (request .user ,params_role ):
@@ -88,7 +89,7 @@ def _get_one(self,key):
8889 if params_role == "OWNER" :
8990 owner_filtered ,q = self ._filter_owner (model ,model_setting ,q )
9091 if not owner_filtered :
91- return json ({"code" :400 ,"msg" :"'%s' cannot filter with owner" % (modelname )})
92+ return json ({"code" :400 ,"msg" :"'%s' cannot filter with owner" % (model_name )})
9293
9394 params = self .request_data [key ]
9495 if isinstance (params ,dict ):
@@ -99,7 +100,7 @@ def _get_one(self,key):
99100 elif hasattr (model ,n ):
100101 q = q .filter (getattr (model .c ,n )== params [n ])
101102 else :
102- return json ({"code" :400 ,"msg" :"'%s' have no attribute '%s'" % (modelname ,n )})
103+ return json ({"code" :400 ,"msg" :"'%s' have no attribute '%s'" % (model_name ,n )})
103104 o = q .one ()
104105 if o :
105106 o = o .to_dict ()
@@ -116,7 +117,7 @@ def _get_one(self,key):
116117
117118 def _get_array (self ,key ):
118119 params = self .request_data [key ]
119- modelname = None
120+ model_name = None
120121 model_param = None
121122 model_column_set = None
122123
@@ -147,14 +148,14 @@ def _get_array(self,key):
147148 for n in params :
148149 if n [0 ]!= "@" :
149150 # TODO: support join in the future, now only support 1 model
150- modelname = n
151+ model_name = n
151152 break
152153
153- if not modelname :
154+ if not model_name :
154155 return json ({"code" :400 ,"msg" :"no model found in array query" })
155156
156157 #model settings
157- model_setting = settings .APIJSON_MODELS .get (modelname ,{})
158+ model_setting = settings .APIJSON_MODELS .get (model_name ,{})
158159 secret_fields = model_setting .get ("secret_fields" )
159160
160161 #model params
@@ -164,18 +165,18 @@ def _get_array(self,key):
164165 if model_column :
165166 model_column_set = set (model_column .split ("," ))
166167 try :
167- model = getattr (models ,modelname )
168+ model = getattr (models ,model_name )
168169 except ModelNotFound as e :
169- log .error ("try to find model '%s' but not found: '%s'" % (modelname ,e ))
170- return json ({"code" :400 ,"msg" :"model '%s' not found" % (modelname )})
170+ log .error ("try to find model '%s' but not found: '%s'" % (model_name ,e ))
171+ return json ({"code" :400 ,"msg" :"model '%s' not found" % (model_name )})
171172 #order
172173 model_order = model_param .get ("@order" )
173174
174175 q = model .all ()
175176
176177 GET = model_setting .get ("GET" )
177178 if not GET :
178- return json ({"code" :400 ,"msg" :"'%s' not accessible by apijson" % (modelname )})
179+ return json ({"code" :400 ,"msg" :"'%s' not accessible by apijson" % (model_name )})
179180
180181 roles = GET .get ("roles" )
181182 params_role = model_param .get ("@role" )
@@ -186,7 +187,7 @@ def _get_array(self,key):
186187 else :
187188 params_role = "UNKNOWN"
188189 if params_role not in roles :
189- return json ({"code" :400 ,"msg" :"'%s' not accessible by role '%s'" % (modelname ,params_role )})
190+ return json ({"code" :400 ,"msg" :"'%s' not accessible by role '%s'" % (model_name ,params_role )})
190191 if params_role == "UNKNOWN" :
191192 permission_check_ok = True
192193 elif functions .has_role (request .user ,params_role ):
@@ -200,21 +201,18 @@ def _get_array(self,key):
200201 if params_role == "OWNER" :
201202 owner_filtered ,q = self ._filter_owner (model ,model_setting ,q )
202203 if not owner_filtered :
203- return json ({"code" :400 ,"msg" :"'%s' cannot filter with owner" % (modelname )})
204+ return json ({"code" :400 ,"msg" :"'%s' cannot filter with owner" % (model_name )})
204205
205- for n in model_param :
206- if n [0 ]!= "@" :
207- if n [- 1 ]== "$" :
208- name = n [:- 1 ]
209- if hasattr (model ,name ):
210- q = q .filter (getattr (model .c ,name ).like (model_param [n ]))
211- elif n [- 1 ]== "}" and n [- 2 ]== "{" :
212- name = n [:- 2 ]
213- if hasattr (model ,name ):
214- # TODO
215- pass
216- elif hasattr (model ,n ):
217- q = q .filter (getattr (model .c ,n )== model_param [n ])
206+ model_expr = model_param .get ("@expr" )
207+
208+ if model_expr :
209+ c = self ._expr (model ,model_param ,model_expr )
210+ q = q .filter (c )
211+ else :
212+ for n in model_param :
213+ if n [0 ]!= "@" :
214+ c = self ._get_filter_condition (model ,model_param ,n )
215+ q = q .filter (c )
218216
219217 if query_type in [1 ,2 ]:
220218 self .vars ["/%s/total" % (key )] = q .count ()
@@ -264,6 +262,60 @@ def _filter_owner(self,model,model_setting,q):
264262 owner_filtered = True
265263 return owner_filtered ,q
266264
265+ def _expr (self ,model ,model_param ,model_expr ):
266+ if not isinstance (model_expr ,list ):
267+ raise UliwebError ("only accept array in @expr: '%s'" % (model_expr ))
268+ num = len (model_expr )
269+ if (num < 2 or num > 3 ):
270+ raise UliwebError ("only accept 2 or 3 items in @expr: '%s'" % (model_expr ))
271+ op = model_expr [- 2 ]
272+ if op == '&' :
273+ if num != 3 :
274+ raise UliwebError ("'&'(and) expression need 3 items: '%s'" % (model_expr ))
275+ c1 = self ._get_filter_condition (model ,model_param ,model_expr [0 ],expr = True )
276+ c2 = self ._get_filter_condition (model ,model_param ,model_expr [2 ],expr = True )
277+ return and_ (c1 ,c2 )
278+ elif op == '|' :
279+ if num != 3 :
280+ raise UliwebError ("'|'(or) expression need 3 items: '%s'" % (model_expr ))
281+ c1 = self ._get_filter_condition (model ,model_param ,model_expr [0 ],expr = True )
282+ c2 = self ._get_filter_condition (model ,model_param ,model_expr [2 ],expr = True )
283+ return or_ (c1 ,c2 )
284+ elif op == '!' :
285+ if num != 2 :
286+ raise UliwebError ("'!'(not) expression need 2 items: '%s'" % (model_expr ))
287+ return not_ (self ._get_filter_condition (model ,model_param ,model_expr [1 ],expr = True ))
288+ else :
289+ raise UliwebError ("unknown operator: '%s'" % (op ))
290+
291+ def _get_filter_condition (self ,model ,model_param ,item ,expr = False ):
292+ if isinstance (item ,list ):
293+ if expr :
294+ return self ._expr (model ,model_param ,model_expr = item )
295+ else :
296+ raise UliwebError ("item can be array only in @expr: '%s'" % (item ))
297+ if not isinstance (item ,str ):
298+ raise UliwebError ("item should be array or string: '%s'" % (item ))
299+ n = item
300+ if n [0 ]== "@" :
301+ raise UliwebError ("param key should not begin with @: '%s'" % (n ))
302+ if n [- 1 ]== "$" :
303+ name = n [:- 1 ]
304+ if hasattr (model ,name ):
305+ return getattr (model .c ,name ).like (model_param [n ])
306+ else :
307+ raise UliwebError ("'%s' does not have '%s'" % (model_name ,name ))
308+ elif n [- 1 ]== "}" and n [- 2 ]== "{" :
309+ name = n [:- 2 ]
310+ if hasattr (model ,name ):
311+ # TODO
312+ pass
313+ raise UliwebError ("still not support '%s'" % (name ))
314+ elif hasattr (model ,n ):
315+ return getattr (model .c ,n )== model_param [n ]
316+ else :
317+ raise UliwebError ("not support item: '%s'" % (item ))
318+
267319 def head (self ):
268320 try :
269321 for key in self .request_data :
@@ -278,22 +330,22 @@ def head(self):
278330 return json (self .rdict )
279331
280332 def _head (self ,key ):
281- modelname = key
333+ model_name = key
282334 params = self .request_data [key ]
283335 params_role = params .get ("@role" )
284336
285337 try :
286- model = getattr (models ,modelname )
287- model_setting = settings .APIJSON_MODELS .get (modelname ,{})
338+ model = getattr (models ,model_name )
339+ model_setting = settings .APIJSON_MODELS .get (model_name ,{})
288340 except ModelNotFound as e :
289- log .error ("try to find model '%s' but not found: '%s'" % (modelname ,e ))
290- return json ({"code" :400 ,"msg" :"model '%s' not found" % (modelname )})
341+ log .error ("try to find model '%s' but not found: '%s'" % (model_name ,e ))
342+ return json ({"code" :400 ,"msg" :"model '%s' not found" % (model_name )})
291343
292344 q = model .all ()
293345
294346 HEAD = model_setting .get ("HEAD" )
295347 if not HEAD :
296- return json ({"code" :400 ,"msg" :"'%s' not accessible" % (modelname )})
348+ return json ({"code" :400 ,"msg" :"'%s' not accessible" % (model_name )})
297349
298350 roles = HEAD .get ("roles" )
299351 permission_check_ok = False
@@ -303,7 +355,7 @@ def _head(self,key):
303355 else :
304356 params_role = "UNKNOWN"
305357 if params_role not in roles :
306- return json ({"code" :400 ,"msg" :"'%s' not accessible by role '%s'" % (modelname ,params_role )})
358+ return json ({"code" :400 ,"msg" :"'%s' not accessible by role '%s'" % (model_name ,params_role )})
307359 if params_role == "UNKNOWN" :
308360 permission_check_ok = True
309361 elif functions .has_role (request .user ,params_role ):
@@ -316,14 +368,14 @@ def _head(self,key):
316368 if params_role == "OWNER" :
317369 owner_filtered ,q = self ._filter_owner (model ,model_setting ,q )
318370 if not owner_filtered :
319- return json ({"code" :400 ,"msg" :"'%s' cannot filter with owner" % (modelname )})
371+ return json ({"code" :400 ,"msg" :"'%s' cannot filter with owner" % (model_name )})
320372 for n in params :
321373 if n [0 ]== "@" :
322374 pass
323375 else :
324376 param = params [n ]
325377 if not hasattr (model .c ,n ):
326- return json ({"code" :400 ,"msg" :"'%s' don't have field '%s'" % (modelname ,n )})
378+ return json ({"code" :400 ,"msg" :"'%s' don't have field '%s'" % (model_name ,n )})
327379 q = model .filter (getattr (model .c ,n )== param )
328380 rdict = {
329381 "code" :200 ,
@@ -370,10 +422,9 @@ def _post_one(self,key,tag):
370422 log .error ("try to find model '%s' but not found: '%s'" % (model_name ,e ))
371423 return json ({"code" :400 ,"msg" :"model '%s' not found" % (model_name )})
372424
373- request_tag_config = request_tag .get (model_name ,{})
374- if not request_tag_config :
425+ if not request_tag :
375426 return json ({"code" :400 ,"msg" :"tag '%s' not found" % (tag )})
376- tag_POST = request_tag_config .get ("POST" ,{})
427+ tag_POST = request_tag .get ("POST" ,{})
377428 if not tag_POST :
378429 return json ({"code" :400 ,"msg" :"tag '%s' not support apijson_post" % (tag )})
379430 ADD = tag_POST .get ("ADD" )
@@ -482,10 +533,9 @@ def _put_one(self,key,tag):
482533 log .error ("try to find model '%s' but not found: '%s'" % (model_name ,e ))
483534 return json ({"code" :400 ,"msg" :"model '%s' not found" % (model_name )})
484535
485- request_tag_config = request_tag .get (model_name ,{})
486- if not request_tag_config :
536+ if not request_tag :
487537 return json ({"code" :400 ,"msg" :"tag '%s' not found" % (tag )})
488- tag_PUT = request_tag_config .get ("PUT" ,{})
538+ tag_PUT = request_tag .get ("PUT" ,{})
489539 ADD = tag_PUT .get ("ADD" )
490540 if ADD :
491541 ADD_role = ADD .get ("@role" )
@@ -604,10 +654,9 @@ def _delete_one(self,key,tag):
604654 log .error ("try to find model '%s' but not found: '%s'" % (model_name ,e ))
605655 return json ({"code" :400 ,"msg" :"model '%s' not found" % (model_name )})
606656
607- request_tag_config = request_tag .get (model_name ,{})
608- if not request_tag_config :
657+ if not request_tag :
609658 return json ({"code" :400 ,"msg" :"tag '%s' not found" % (tag )})
610- tag_DELETE = request_tag_config .get ("DELETE" ,{})
659+ tag_DELETE = request_tag .get ("DELETE" ,{})
611660 ADD = tag_DELETE .get ("ADD" )
612661 if ADD :
613662 ADD_role = ADD .get ("@role" )
0 commit comments