Skip to content

Commit 573f744

Browse files
authored
Merge pull request APIJSON#28 from zhangchunlin/master
Sync
2 parents 600cafe + 214bdc2 commit 573f744

File tree

3 files changed

+140
-57
lines changed

3 files changed

+140
-57
lines changed

demo/apps/apijson_demo/templates/index.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,11 @@
101101
el: '#app',
102102
delimiters: ['{', '}'],
103103
data: {
104-
request_get : {{=request_get_json}},
105-
request_head : {{=request_head_json}},
106-
request_post : {{=request_post_json}},
107-
request_put : {{=request_put_json}},
108-
request_delete : {{=request_delete_json}},
104+
request_get : {{<<request_get_json}},
105+
request_head : {{<<request_head_json}},
106+
request_post : {{<<request_post_json}},
107+
request_put : {{<<request_put_json}},
108+
request_delete : {{<<request_delete_json}},
109109
request_data : "",
110110
select_current : "",
111111
can_post : true,

demo/apps/apijson_demo/views.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,41 @@ def index():
7777
"username$":"%user%"
7878
}
7979
}
80+
}''',
81+
},
82+
{
83+
"label":"Array query: simple @expr",
84+
"value":'''{
85+
"[]":{
86+
"@count":4,
87+
"@page":0,
88+
"user":{
89+
"@column":"id,username,nickname,email",
90+
"@order":"id-",
91+
"@role":"ADMIN",
92+
"@expr":["username$","|","nickname$"],
93+
"username$":"%b%",
94+
"nickname$":"%c%"
95+
}
96+
}
97+
}''',
98+
},
99+
{
100+
"label":"Array query: complex @expr",
101+
"value":'''{
102+
"[]":{
103+
"@count":4,
104+
"@page":0,
105+
"user":{
106+
"@column":"id,username,nickname,email",
107+
"@order":"id-",
108+
"@role":"ADMIN",
109+
"@expr":[["username$","&","email$"],"&",["!","nickname$"]],,
110+
"username$":"%b%",
111+
"nickname$":"%Admin%",
112+
"email$":"%local%"
113+
}
114+
}
80115
}''',
81116
},
82117
]
@@ -141,7 +176,6 @@ def index():
141176
}''',
142177
},
143178
]
144-
145179
return {
146180
"user_info":user_info,
147181
"request_get_json":dumps(request_get),

uliweb_apijson/apijson/views.py

Lines changed: 100 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#coding=utf-8
2-
from uliweb import expose, functions, models
2+
from uliweb import expose, functions, models, UliwebError
33
from uliweb.orm import ModelNotFound
4+
from sqlalchemy.sql import and_, or_, not_
45
from json import loads
56
import logging
67
import 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

Comments
 (0)