Skip to content

Commit 8844488

Browse files
authored
Merge pull request #44 from zhangchunlin/master
Sync
2 parents a922272 + 4ee6f67 commit 8844488

File tree

4 files changed

+317
-12
lines changed

4 files changed

+317
-12
lines changed

demo/apps/apijson_demo/views.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,28 @@ def index():
8585
}''',
8686
},
8787

88+
{
89+
"label":"Array query: {} with list",
90+
"value":'''{
91+
"[]":{
92+
"moment":{
93+
"id{}":[2,3]
94+
}
95+
}
96+
}''',
97+
},
98+
99+
{
100+
"label":"Array query: {} with conditions",
101+
"value":'''{
102+
"[]":{
103+
"user":{
104+
"id&{}":">2,<=4"
105+
}
106+
}
107+
}''',
108+
},
109+
88110
{
89111
"label":"Array query: simple @expr",
90112
"value":'''{

tests/test.py

Lines changed: 235 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ def setup():
1111
manage.call('uliweb reset -v -y')
1212
manage.call('uliweb dbinit -v')
1313

14-
def teardown():
15-
pass
16-
1714
def pre_call_as(username):
1815
from uliweb import models
1916
User = models.user
@@ -22,7 +19,6 @@ def pre_call(request):
2219
request.user = user
2320
return pre_call
2421

25-
@with_setup(setup,teardown)
2622
def test_apijson_get():
2723
"""
2824
>>> application = make_simple_application(project_dir='.')
@@ -747,7 +743,7 @@ def test_apijson_get():
747743
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
748744
>>> d = json_loads(r.data)
749745
>>> print(d)
750-
{'code': 400, 'msg': "model does not have this column: 'nonexist'"}
746+
{'code': 400, 'msg': "model does not have column: 'nonexist'"}
751747
752748
>>> #query array with a nonexist column
753749
>>> data ='''{
@@ -767,6 +763,240 @@ def test_apijson_get():
767763
>>> print(d)
768764
{'code': 400, 'msg': "non-existent column or not support item: 'nonexist'"}
769765
766+
>>> #query array, {} with list
767+
>>> data ='''{
768+
... "[]":{
769+
... "moment": {
770+
... "id{}": [1, 2]
771+
... }
772+
... }
773+
... }'''
774+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
775+
>>> d = json_loads(r.data)
776+
>>> print(d)
777+
{'code': 200, 'msg': 'success', '[]': [{'moment': {'user_id': 2, 'date': '2018-11-01 00:00:00', 'content': 'test moment', 'picture_list': '[]', 'id': 1}}, {'moment': {'user_id': 3, 'date': '2018-11-02 00:00:00', 'content': 'test moment from b', 'picture_list': '[]', 'id': 2}}]}
778+
779+
>>> #query array, !{} with list
780+
>>> data ='''{
781+
... "[]":{
782+
... "moment": {
783+
... "id!{}": [1, 2]
784+
... }
785+
... }
786+
... }'''
787+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
788+
>>> d = json_loads(r.data)
789+
>>> print(d)
790+
{'code': 200, 'msg': 'success', '[]': [{'moment': {'user_id': 4, 'date': '2018-11-06 00:00:00', 'content': 'test moment from c', 'picture_list': '[]', 'id': 3}}]}
791+
792+
>>> #query array, {} with a non-exist column name
793+
>>> data ='''{
794+
... "[]":{
795+
... "moment": {
796+
... "nonexist{}": [1, 2]
797+
... }
798+
... }
799+
... }'''
800+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
801+
>>> d = json_loads(r.data)
802+
>>> print(d)
803+
{'code': 400, 'msg': "model does not have column: 'nonexist'"}
804+
805+
>>> #query array, {} >=
806+
>>> data ='''{
807+
... "[]":{
808+
... "moment": {
809+
... "id{}": ">=2"
810+
... }
811+
... }
812+
... }'''
813+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
814+
>>> d = json_loads(r.data)
815+
>>> print(d)
816+
{'code': 200, 'msg': 'success', '[]': [{'moment': {'user_id': 3, 'date': '2018-11-02 00:00:00', 'content': 'test moment from b', 'picture_list': '[]', 'id': 2}}, {'moment': {'user_id': 4, 'date': '2018-11-06 00:00:00', 'content': 'test moment from c', 'picture_list': '[]', 'id': 3}}]}
817+
818+
>>> #query array, {} =
819+
>>> data ='''{
820+
... "[]":{
821+
... "moment": {
822+
... "id{}": "=2"
823+
... }
824+
... }
825+
... }'''
826+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
827+
>>> d = json_loads(r.data)
828+
>>> print(d)
829+
{'code': 200, 'msg': 'success', '[]': [{'moment': {'user_id': 3, 'date': '2018-11-02 00:00:00', 'content': 'test moment from b', 'picture_list': '[]', 'id': 2}}]}
830+
831+
>>> #query array, {} >
832+
>>> data ='''{
833+
... "[]":{
834+
... "moment": {
835+
... "id{}": ">2"
836+
... }
837+
... }
838+
... }'''
839+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
840+
>>> d = json_loads(r.data)
841+
>>> print(d)
842+
{'code': 200, 'msg': 'success', '[]': [{'moment': {'user_id': 4, 'date': '2018-11-06 00:00:00', 'content': 'test moment from c', 'picture_list': '[]', 'id': 3}}]}
843+
844+
>>> #query array, {} <=
845+
>>> data ='''{
846+
... "[]":{
847+
... "moment": {
848+
... "id{}": "<=2"
849+
... }
850+
... }
851+
... }'''
852+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
853+
>>> d = json_loads(r.data)
854+
>>> print(d)
855+
{'code': 200, 'msg': 'success', '[]': [{'moment': {'user_id': 2, 'date': '2018-11-01 00:00:00', 'content': 'test moment', 'picture_list': '[]', 'id': 1}}, {'moment': {'user_id': 3, 'date': '2018-11-02 00:00:00', 'content': 'test moment from b', 'picture_list': '[]', 'id': 2}}]}
856+
857+
>>> #query array, {} <
858+
>>> data ='''{
859+
... "[]":{
860+
... "moment": {
861+
... "id{}": "<2"
862+
... }
863+
... }
864+
... }'''
865+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
866+
>>> d = json_loads(r.data)
867+
>>> print(d)
868+
{'code': 200, 'msg': 'success', '[]': [{'moment': {'user_id': 2, 'date': '2018-11-01 00:00:00', 'content': 'test moment', 'picture_list': '[]', 'id': 1}}]}
869+
870+
>>> #query array, !{} <
871+
>>> data ='''{
872+
... "[]":{
873+
... "moment": {
874+
... "id!{}": "<2"
875+
... }
876+
... }
877+
... }'''
878+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
879+
>>> d = json_loads(r.data)
880+
>>> print(d)
881+
{'code': 200, 'msg': 'success', '[]': [{'moment': {'user_id': 3, 'date': '2018-11-02 00:00:00', 'content': 'test moment from b', 'picture_list': '[]', 'id': 2}}, {'moment': {'user_id': 4, 'date': '2018-11-06 00:00:00', 'content': 'test moment from c', 'picture_list': '[]', 'id': 3}}]}
882+
883+
>>> #query array, {} !=
884+
>>> data ='''{
885+
... "[]":{
886+
... "moment": {
887+
... "id{}": "!=2"
888+
... }
889+
... }
890+
... }'''
891+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
892+
>>> d = json_loads(r.data)
893+
>>> print(d)
894+
{'code': 200, 'msg': 'success', '[]': [{'moment': {'user_id': 2, 'date': '2018-11-01 00:00:00', 'content': 'test moment', 'picture_list': '[]', 'id': 1}}, {'moment': {'user_id': 4, 'date': '2018-11-06 00:00:00', 'content': 'test moment from c', 'picture_list': '[]', 'id': 3}}]}
895+
896+
>>> #query array, {} with wrong operator
897+
>>> data ='''{
898+
... "[]":{
899+
... "moment": {
900+
... "id{}": "%=2"
901+
... }
902+
... }
903+
... }'''
904+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
905+
>>> d = json_loads(r.data)
906+
>>> print(d)
907+
{'code': 400, 'msg': "not support '%=2'"}
908+
909+
>>> #query array, {} condition list
910+
>>> data ='''{
911+
... "[]":{
912+
... "user": {
913+
... "@role": "ADMIN",
914+
... "id{}": "<=2,>3",
915+
... "@column": "username,nickname,id"
916+
... }
917+
... }
918+
... }'''
919+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
920+
>>> d = json_loads(r.data)
921+
>>> print(d)
922+
{'code': 200, 'msg': 'success', '[]': [{'user': {'username': 'admin', 'nickname': 'Administrator', 'id': 1}}, {'user': {'username': 'usera', 'nickname': 'User A', 'id': 2}}, {'user': {'username': 'userc', 'nickname': 'User C', 'id': 4}}]}
923+
924+
>>> #query array, |{} condition list
925+
>>> data ='''{
926+
... "[]":{
927+
... "user": {
928+
... "@role": "ADMIN",
929+
... "id|{}": "<=2,>3",
930+
... "@column": "username,nickname,id"
931+
... }
932+
... }
933+
... }'''
934+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
935+
>>> d = json_loads(r.data)
936+
>>> print(d)
937+
{'code': 200, 'msg': 'success', '[]': [{'user': {'username': 'admin', 'nickname': 'Administrator', 'id': 1}}, {'user': {'username': 'usera', 'nickname': 'User A', 'id': 2}}, {'user': {'username': 'userc', 'nickname': 'User C', 'id': 4}}]}
938+
939+
>>> #query array, &{} condition list
940+
>>> data ='''{
941+
... "[]":{
942+
... "user": {
943+
... "@role": "ADMIN",
944+
... "id&{}": ">2,<=4",
945+
... "@column": "username,nickname,id"
946+
... }
947+
... }
948+
... }'''
949+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
950+
>>> d = json_loads(r.data)
951+
>>> print(d)
952+
{'code': 200, 'msg': 'success', '[]': [{'user': {'username': 'userb', 'nickname': 'User B', 'id': 3}}, {'user': {'username': 'userc', 'nickname': 'User C', 'id': 4}}]}
953+
954+
>>> #query array, {} multiple condition to a same field
955+
>>> data ='''{
956+
... "[]":{
957+
... "user": {
958+
... "@role": "ADMIN",
959+
... "id&{}": ">2,<=4",
960+
... "id{}": "!=3",
961+
... "@column": "username,nickname,id"
962+
... }
963+
... }
964+
... }'''
965+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
966+
>>> d = json_loads(r.data)
967+
>>> print(d)
968+
{'code': 200, 'msg': 'success', '[]': [{'user': {'username': 'userc', 'nickname': 'User C', 'id': 4}}]}
969+
970+
>>> #query array, !{} condition list
971+
>>> data ='''{
972+
... "[]":{
973+
... "user": {
974+
... "@role": "ADMIN",
975+
... "id!{}": ">2,<=4",
976+
... "@column": "username,nickname,id"
977+
... }
978+
... }
979+
... }'''
980+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
981+
>>> d = json_loads(r.data)
982+
>>> print(d)
983+
{'code': 400, 'msg': "'!' not supported in condition list"}
984+
985+
>>> #query array, |{} condition list, item more than 2
986+
>>> data ='''{
987+
... "[]":{
988+
... "user": {
989+
... "@role": "ADMIN",
990+
... "id|{}": "=1,=2,>=4",
991+
... "@column": "username,id"
992+
... }
993+
... }
994+
... }'''
995+
>>> r = handler.post('/apijson/get', data=data, pre_call=pre_call_as("admin"), middlewares=[])
996+
>>> d = json_loads(r.data)
997+
>>> print(d)
998+
{'code': 200, 'msg': 'success', '[]': [{'user': {'username': 'admin', 'id': 1}}, {'user': {'username': 'usera', 'id': 2}}, {'user': {'username': 'userc', 'id': 4}}]}
999+
7701000
>>> #Association query: Two tables, one to one,ref path is absolute path
7711001
>>> data ='''{
7721002
... "moment":{},

uliweb_apijson/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = '0.2.1'
1+
__version__ = '0.2.2'
22
__url__ = 'https://github.com/zhangchunlin/uliweb-apijson'
33
__author__ = 'Chunlin Zhang'
44
__email__ = 'zhangchunlin@gmail.com'

uliweb_apijson/apijson/views.py

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -244,18 +244,71 @@ def _get_filter_condition(self,model,model_param,item,expr=False):
244244
if hasattr(model,name):
245245
return getattr(model.c,name).like(model_param[n])
246246
else:
247-
raise UliwebError("model does not have this column: '%s'"%(name))
247+
raise UliwebError("model does not have column: '%s'"%(name))
248248
elif n[-1]=="}" and n[-2]=="{":
249-
name = n[:-2]
250-
if hasattr(model,name):
251-
# TODO: https://github.com/APIJSON/APIJSON/blob/master/Document.md#32-%E5%8A%9F%E8%83%BD%E7%AC%A6
252-
pass
253-
raise UliwebError("still not support '%s'"%(name))
249+
if n[-3] in ["&","|","!"]:
250+
operator = n[-3]
251+
name = n[:-3]
252+
else:
253+
operator = None
254+
name = n[:-2]
255+
256+
if not hasattr(model,name):
257+
raise UliwebError("model does not have column: '%s'"%(name))
258+
259+
# https://github.com/APIJSON/APIJSON/blob/master/Document.md#32-%E5%8A%9F%E8%83%BD%E7%AC%A6
260+
# https://vincentcheng.github.io/apijson-doc/zh/grammar.html#%E9%80%BB%E8%BE%91%E8%BF%90%E7%AE%97-%E7%AD%9B%E9%80%89
261+
col = getattr(model.c,name)
262+
cond = model_param[n]
263+
if isinstance(cond,list):
264+
fcond = col.in_(cond)
265+
if operator== "!":
266+
fcond = not_(fcond)
267+
return fcond
268+
elif isinstance(cond,str):
269+
cond_list = cond.strip().split(",")
270+
if len(cond_list)==1:
271+
fcond = self._get_filter_condition_from_str(col,cond_list[0])
272+
if operator=="!":
273+
fcond = not_(fcond)
274+
return fcond
275+
elif len(cond_list)>1:
276+
fcond = self._get_filter_condition_from_str(col,cond_list[0])
277+
for c in cond_list:
278+
fc = self._get_filter_condition_from_str(col,c)
279+
if operator=="&":
280+
fcond = and_(fcond,fc)
281+
elif operator=="|" or operator==None:
282+
fcond = or_(fcond,fc)
283+
else:
284+
raise UliwebError("'%s' not supported in condition list"%(operator))
285+
return fcond
286+
287+
raise UliwebError("not support '%s':'%s'"%(n,cond))
254288
elif hasattr(model,n):
255289
return getattr(model.c,n)==model_param[n]
256290
else:
257291
raise UliwebError("non-existent column or not support item: '%s'"%(item))
258292

293+
def _get_filter_condition_from_str(self,col,cond_str):
294+
cond_str = cond_str.strip()
295+
c1,c2 = cond_str[0],cond_str[1]
296+
if c1=='>':
297+
if c2=="=":
298+
return col >= cond_str[2:]
299+
else:
300+
return col > cond_str[1:]
301+
elif c1=='<':
302+
if c2=="=":
303+
return col <= cond_str[2:]
304+
else:
305+
return col < cond_str[1:]
306+
elif c1=="=":
307+
return col == cond_str[1:]
308+
elif c1=="!" and c2=="=":
309+
return col != cond_str[2:]
310+
raise UliwebError("not support '%s'"%(cond_str))
311+
259312
def head(self):
260313
try:
261314
for key in self.request_data:

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy