API装饰器

apidecorators的Python项目详细描述


API装饰器

为aiohttp和mongodb定义rest模式。

pip install apidecorators

此api对模式有效,方式如下:

架构={ *原语 *对象 *基元数组 *对象数组 }

其中对象是原语和此类对象的对象。

让我举例说明:

fromapidecorators.apiimportjwt_auth,get,insert,has_role,update,push,pull, \
                validate,get_many,delete,read_access,write_access,collection,aggregate, \
                update_array,get_from_array,publicfromapidecorators.fieldsimportall_fieldsfromcerberusimportValidator#given this schemas_budget={'_id':{'type':'string'},'applicant':{'type':'string'},'offerer':{'type':'string'},'description':{'type':'string','required':True},'amount':{'type':'integer'},'favorite':{'type':'boolean'},'comment':{'type':'dict','schema':{"text":{"type":"string"},"date":{"type":"float"}}}}s_demand={'_id':{'type':'string'},'applicant':{'type':'string'},'description':{'type':'string','required':True},'location':{'type':'string'},'budgets':{'type':'list','schema':s_budget}}v_demand=Validator(s_demand)v_budget=Validator(s_budget)# we define a POST this waydefset_routes_demand(routes):@routes.post('/api/demand')# aiohttp routes@jwt_auth# must receive a valid JWT token@collection('demand')# which collection@write_access({'*':'*'})# any user can write any field@validate(validator=v_demanda)# set the cerberus validator@insert# it will be an insertasyncdefpost_demand(document,request,token):document['applicant']=token['user']returndocument# the returned document will be written in the collection described above# we GET a document this way:@routes.get('/api/demand/{_id}')@jwt_auth@collection('demand')# the user stores in the field applicant can read all fields minus location# any other user can read only description and location@read_access({'applicant':all_fields(s_demand)-{'location'},'*':{'description','location'}})@get# it will be a getasyncdefget_demand(document,token):# the last chance to change the document that will be sent to the client    returndocument# we PUT a document this way:@routes.put('/api/demand/{_id}')@jwt_auth@collection('demand')@write_access({'applicant':{'description','location'}})@validate(update=True,validator=v_demanda)# see the attribute update=True@update# it will be an updateasyncdefput_demand(old_doc,document,request,token):returndocument# let see how to push to an array:@routes.put('/api/demand/{_id}/budgets')@jwt_auth@collection('demand')@write_access({'*':{'description','amount'}})@validate(validator=v_budget)@push('budgets')# the name of the arrayasyncdefpush_budget(old_doc,document,request,token):document['offerer']=token['user']document['applicant']=old_doc['applicant']returndocument# update an element of an array@routes.put('/api/demand/{_id}/budgets/{sub_id}')@jwt_auth@collection('demand')# the user stores in offerer field of subdocument (sub_id) can update description and amount# the user stores in applicant field of subdocument (sub_id) can update favorite and comment# if you pass root a value different from '.', that will be the root where to check users of write_access@write_access({'offerer':{'description','amount'},'applicant':{'favorite','comment'}},root='budgets')@update_array('budgets')asyncdefupdate_budgets(old_doc,document,token):returndocument# get many@routes.get('/api/demand')@public@collection('demand')@read_access({'*':'*'})@get_manyasyncdefget_many_demands(col,query,token):applicant=query["applicant"]returncol.find({"applicant":applicant}).skip(0).limit(10)# get from an array@routes.get('/api/demanddemand/{_id}/budgets')@jwt_auth@collection('demand')@read_access({'offerer':{'description','amount'}})@get_from_array('budgets')asyncdefget_presupuestos(document,token):#the chance to remove empty objects in array   returndocument# and you can do aggregates@routes.get('/api/demand/aggregates/comments')@public# it is not restricted by a JWT token, the user will be anonymous@collection('demand')@aggregateasyncdefget_aggr_comments(col,query,token):offerer=query["offerer"]pipeline=[{"$match":{"budgets.offerer":offerer}},{"$unwind":"$budgets"},{"$match":{"budgets.offerer":offerer}},{"$group":{"_id":"$budgets.offerer","comments":{"$push":{"text":"$budgets.comment.text","date":"$budgets.comment.date","author":"$applicant"}}}}]returncol.aggregate(pipeline)

在read_access和write_access中,可以对数组使用点表示法和$。示例:

@read_access({'applicant':all_fields(s_demand)|{'budgets.$.comment'}})
#app.pyimportasynciofromdemandimportset_routes_demandfromaiohttpimportwebfromapidecorators.apiimportcors_factoryasyncdefhandle(loop):app=web.Application(loop=loop,middlewares=[cors_factory])routes=web.RouteTableDef()set_routes_demand(routes)app.router.add_routes(routes)awaitloop.create_server(app.make_handler(),'0.0.0.0',8888)defmain():loop=asyncio.get_event_loop()loop.run_until_complete(handle(loop))print("Server started at port 8888")loop.run_forever()loop.close()if__name__=='__main__':main()

docker-compose.yml

    environment:
    - DB_URI=mongodb://<user>:<password>@url:port/data-base
    - DB=data-base
    - SECRET=secret

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java使Eclipse在其控制台中显示最顶层的异常,而不是完整的堆栈跟踪   java如何为一个组件提供多个DropTargetListener?   在Eclipse包资源管理器中,有些文件不可见?   java在Spring Boot中使用@Bean配置设置类属性的默认值   在JTextPane中使用#链接的Java HTML?   java当应用程序打开时,如何将通知内容发送给活动?   java Android ROOM如何编写包含多个实体的查询,这是在哪里完成的?   Play Framework的java登录/注销问题?   java如何从安卓 Cordova/Phonegap调用javascript函数   JavaFX8如何在Java8中显示上次修改的LocalDateTime?   javabean验证中的多个约束注释   java使用JSTL设置请求属性   java在Android启动的服务中调用函数   用于检查xml是否包含键和值的java XPath表达式   在java游戏中使用斜坡因子挥杆   Java文件:尝试使用FileWriter将结果附加到已经存在的文件中   bootclasspath Java Xbootclasspath,相对路径   java我如何让这个“怪物战斗模拟器”工作?   swing使用动作侦听器隐藏和显示java桌面应用程序