def get(self): """Get all data """ # one to many # 1. parsing reqest try: # FIXME: # when i assign field_inputs['name']['required'] to True, # it could through below error: # ValueError: [name]: (name Valid Error) Missing required parameter # in dataDict # but i have no idea what it happen. if os.environ.get('EVN'): # in unit test field_inputs['name']['required'] = False logger.warning('now we are in unit test mode, turn off'\ ' field_inputs[\'name\'][\'required\']'\ ' but 1st run is ok :(') self.args = GetRequest( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[__heads__] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(grp, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') r = grp.query.order_by(isDesc()) _r = r.all() self.args['total'] = len(_r) if itemsPerPage is not 0: _r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() r = _r # 2. export to user data, field = SerialGroupOutput(r, resource_fields=resource_fields, omitKeys=['id', 'name']) self.args[__heads__] = data _resource_fields_wrap = resource_fields_wrap.copy() _resource_fields_wrap[__heads__] = fields.List(fields.Nested(field)) return marshal(self.args, _resource_fields_wrap), 200
def get(self): # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(__heads__, 'refBy') requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 try: self.args = _reqparse.parse_args() self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[__heads__] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError('CE_INVALID_PARAM', repr(error)), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(obj, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') # .order_by(User.login.desc()) r = obj.query.order_by(isDesc()) if itemsPerPage is 0: r = r.all() else: r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() for _r in r: __r = dict( (col, getattr(_r, col)) for col in _r.__table__.columns.keys()) self.args[__heads__].append(__r) self.args['total'] = len(r) _resource_fields_wrap[__heads__] = {} _resource_fields_wrap[__heads__] = fields.List( fields.Nested(resource_fields)) return marshal(self.args, _resource_fields_wrap), 200
def get(self): """Get all data, getall """ # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(field_inputs_wrap.keys()) requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 # one to many # 1. parsing reqest try: for k, v in field_inputs.items(): field_inputs[k]['required'] = False orgArgs, self.args = GetRequestArgs( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value # print(self.args, 'self.args', resource_fields_wrap) self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[field_inputs_wrap_head] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(obj, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') r = obj.query.filter(obj.isdel == False).order_by(isDesc()) _r = r.all() self.args['total'] = len(_r) if itemsPerPage is not 0: _r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() r = _r # 2. export to user for _r in r: __r = dict( (col, getattr(_r, col)) for col in _r.__table__.columns.keys()) self.args[field_inputs_wrap_head].append(__r) _resource_fields = resource_fields.copy() _resource_fields_wrap = resource_fields_wrap.copy() _resource_fields_wrap[field_inputs_wrap_head] = fields.List( fields.Nested(_resource_fields)) self.args['type'] = "business" self.args['subtype'] = "rate" return marshal(self.args, _resource_fields_wrap), 200
def get(self): """Get all data, getall @api {get} /rest/objects/ipaddrs Read IP Addresses @apiVersion 0.0.1 @apiName GetIpAddrs @apiVersion 0.0.1 @apiGroup objects @apiPermission registered user @apiDescription todo validation @apiParam {Number=0, 25, 50, 100} [itemsPerPage=25] items for each request. @apiParam {Number} [page=1] page you want to request from, start with 1. @apiParam {String="name", "description"} [orderBy=name] the items order by column you specified. @apiParam {String="true", "false"} [desc=false] the items order by descending or asceding order. @apiExample Example usage: curl -i http://localhost/rest/objects/ipaddrs?itemsPerPage=50&page=1&orderBy=name&desc=true @apiSuccess {Number} total total items for pagination. @apiSuccess {String} orderBy the items order by column you specified. @apiSuccess {Number} page page you want to request from, start with 1. @apiSuccess {Number} itemsPerPage items for each request. @apiSuccess {String} desc the items order by descending or asceding order. @apiSuccess {Object[]} ipaddrs List of IP Addresses. @apiSuccess {String} ipaddrs.addr1 1st IP Address. @apiSuccess {String} ipaddrs.addr2 2ed IP Address. @apiSuccess {String} ipaddrs.description this items's description. @apiSuccess {Number} ipaddrs.id index in database. @apiSuccess {String} ipaddrs.ipVersion IP Address version. @apiSuccess {String} ipaddrs.name items uniq name for record. @apiSuccess {String} ipaddrs.type IP Address type, the possible values are 'Single', 'Range', 'Subnet'. @apiError CE_INVALID_PARAM invalid parameter @api {get} /rest/objects/ipaddrs @apiErrorExample {json} we use invalid parameter pages curl -i http://localhost/rest/objects/ipaddrs?pages=1 ================================================ HTTP/1.0 400 BAD REQUEST { "errorId": 2001, "message": "{'pages'}" } """ # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(field_inputs_wrap.keys()) requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 # one to many # 1. parsing reqest try: # FIXME: # when i assign field_inputs['name']['required'] to True, # it could through below error: # ValueError: [name]: (name Valid Error) Missing required parameter # in dataDict # but i have no idea what it happen. if os.environ.get('EVN'): # in unit test field_inputs['name']['required'] = False logger.warning('now we are in unit test mode, turn off'\ ' field_inputs[\'name\'][\'required\']'\ ' but 1st run is ok :(') orgArgs, self.args = GetRequestArgs( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value # print(self.args, 'self.args', resource_fields_wrap) self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[__heads__] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(obj, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') r = obj.query.order_by(isDesc()) _r = r.all() self.args['total'] = len(_r) if itemsPerPage is not 0: _r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() r = _r # 2. export to user for _r in r: __r = dict( (col, getattr(_r, col)) for col in _r.__table__.columns.keys()) self.args[__heads__].append(__r) resource_fields_wrap[__heads__] = fields.List( fields.Nested(resource_fields)) return marshal(self.args, resource_fields_wrap), 200
default='name', argument=['name', 'type', 'description'], ) resource_fields, resource_fields_ref, resource_fields_wrap = GetResource( field_inputs, field_inputs_ref, field_inputs_wrap, __heads__) # not extend to resource_fields field_inputs['name']['required'] = True field_inputs[__obj__heads__] = { 'type': { fields.List( fields.Nested({ 'id': { 'type': fields.Integer(), 'required': True }, 'name': { 'type': fields.String() } })) } } class ObjectIpgroup(Resource): """ entry point about '/rest/objects/ipgroups/<int:id>' when user do below actions: getone/put """ def __init__(self):
def get(self, id): """get one item @api {get} /rest/customer/business/:id get one business @apiName GetCustomerBusiness @apiVersion 0.0.4 @apiGroup customer @apiPermission registered user @apiDescription todo validation<br /> todo query target<br/> @apiParam {Number} id business id, you can get from GetAllCustomerBusinesses. @apiExample Example usage: HTTP/1.0 200 OK { "id": 1, "name": "Starbucks Coffee", "image_url": "/business/1/icon", "cat": 1, "deal": 200, "lat": 120.678469, "long": 23.538302, "description": "Early Bird Special: Get $2 off.", "detail": { "rate": 4.3, "rates": [ {"u_id": 1, "avatar_url": "/user/1/avater"}, {"u_id": 2, "avatar_url": "/user/2/avater"} ], "deals": [ {"title": "morning", "description": "for every one"} ], "open": "0600", "close": "2100", "dist": 12333333, "address": "CA", "images_url": { "bg": "/business/1/bg", "icon": "/business/1/icon" } } } @apiSuccess {Object} business object of business. @apiSuccess {Number} business.id item's uniq id. @apiSuccess {String} business.name item's name. @apiSuccess {Number} business.cat item's business industry category. @apiSuccess {float} business.lat item's entered latitude. @apiSuccess {float} business.long item's entered longitude. @apiSuccess {String} business.address item's address @apiSuccess {String} business.description item's description. @apiSuccess {Number} business.deal item's deal. @apiSuccess {String} business.image_url items's image url. @apiSuccess {Object} business.detail item's detail @apiSuccess {Float} business.detail.rate item's rate, average from each comments @apiSuccess {Object[]} business.detail.rates item's brief comments @apiSuccess {Number} business.detail.rates.u_id comment's author id @apiSuccess {String} business.detail.rates.avatar_url comment's author avatar url path @apiSuccess {Object[]} business.detail.deals item's deals @apiSuccess {String} business.detail.deals.title item's deal title @apiSuccess {String} business.detail.deals.description item's deal description @apiSuccess {String} business.detail.open item open time with 24h format @apiSuccess {String} business.detail.open item close time with 24h format @apiSuccess {Number} business.detail.dist item's distance farward with your current location, the unit is meter @apiSuccess {Object} business.detail.images_url item images' path @apiSuccess {String} business.detail.images_url.bg item backgound images' path @apiSuccess {String} business.detail.images_url.icon item icon images' path @apiError CE_INVALID_PARAM invalid parameter HTTP/1.0 400 BAD REQUEST { "errorId": 2001, "message": "{'pages'}" } @apiError CE_NOT_EXIST item not found HTTP/1.0 400 BAD REQUEST { "errorId": 2003, "message": "id 17 not found" } """ requestArgsSet = set((col) for col in request.args) if not ExtraParamsIsValid(requestArgsSet): return omitError(ErrorMsg=repr(set( (col) for col in request.args))), 400 r = detail.query.filter(detail.business_id == id, detail.isdel == False).scalar() if r is None: return omitError('CE_NOT_EXIST', 'id {} not found'.format(id)), 400 self.args = {} self.args[field_inputs_wrap_head] = {} #self.args[field_inputs_wrap_head][__head_detail__] = {} _resource_fields_wrap = resource_fields_wrap.copy() for col in resource_fields_wrap: if col not in ['type', 'subtype']: _resource_fields_wrap.pop(col, None) #_resource_fields_detail_wrap = {} #resource_fields_detail[__head_detail_rates__] = \ # fields.List(fields.Nested(resource_fields_detail_rates)) resource_fields_detail[__head_detail_deals__] = \ fields.List(fields.Nested(resource_fields_detail_deals)) _resource_fields_detail_rates = {} #_resource_fields_detail_rates['user'] = fields.Nested(resource_fields_detail_rates) _resource_fields_detail_rates = resource_fields_detail_rates.copy() resource_fields_detail['users'] = \ fields.List(fields.Nested(_resource_fields_detail_rates)) #resource_fields.update(resource_fields_detail) resource_fields_detail[__head_detail_images_url__] = \ fields.Nested(resource_fields_detail_images_url) #resource_fields[__head_detail__] = fields.Nested(_resource_fields_detail_wrap) #_resource_fields_wrap[field_inputs_wrap_head] = fields.Nested(resource_fields) _resource_fields_wrap[field_inputs_wrap_head] = fields.Nested( resource_fields_detail) #print('_resource_fields_wrap ', resource_fields) _r = r #for col in resource_fields.keys(): # self.args[field_inputs_wrap_head][col] = getattr(_r, col) #for col in resource_fields.keys(): for col in _r.__table__.columns.keys(): self.args[field_inputs_wrap_head][col] = getattr(_r, col) self.args[field_inputs_wrap_head]['name'] = getattr(_r.meta, 'name') rate = 0 self.args[field_inputs_wrap_head]['rate'] = rate self.args[field_inputs_wrap_head]['users'] = [] self.args[field_inputs_wrap_head][__head_detail_deals__] = [] self.args[field_inputs_wrap_head]['images_url'] = {} __r = db.session.query(rates).\ filter(rates.business_id == id).all() r_len = len(__r) self.args[field_inputs_wrap_head]['rate_nr'] = r_len if r_len > 0: for ___r in __r: rate += ___r.rate self.args[field_inputs_wrap_head]['rate'] = int(rate / r_len) # FIXME: hard code __r = db.session.query(comment).\ filter(comment.business_id == id).order_by(comment.mtime.desc()).offset(0).limit(5).all() r_len = len(__r) self.args[field_inputs_wrap_head]['user_nr'] = r_len if r_len > 0: for __r in __r: ___r = db.session.query(Users).\ filter(__r.user_id == Users.id).scalar() self.args[field_inputs_wrap_head]['users'].append( #{'user': { 'id': ___r.id, 'avatar_url': ___r.avatar_url } #} ) # TODO: get favorite by User id from session _r = deals.query.filter(deals.business_id == id).all() r_len = len(_r) if r_len: for __r in _r: self.args[field_inputs_wrap_head][ __head_detail_deals__].append({ 'title': __r.title, 'description': __r.description }) _r = pics.query.filter(pics.business_id == id).all() # (1, 'icon'), (2, 'bg'), (3, 'gallery') r_len = len(_r) if r_len > 0: # TODO: mapping table for __r in _r: if getattr(__r, 'type') == 1: self.args[field_inputs_wrap_head]['images_url']['icon'] = \ getattr(__r, 'path') r_len -= 1 elif getattr(__r, 'type') == 2: self.args[field_inputs_wrap_head]['images_url']['bg'] = \ getattr(__r, 'path') r_len -= 1 self.args[field_inputs_wrap_head]['gallery_nr'] = r_len self.args[field_inputs_wrap_head]['id'] = id self.args['type'] = "business" self.args['subtype'] = "overview" #print('self.args= ', self.args, '_resource_fields_wrap', _resource_fields_wrap) return marshal(self.args, _resource_fields_wrap), 200
def get(self): """Get all data, getall @api {get} /rest/customer/businesses list business @apiName GetAllCustomerBusinesses @apiVersion 0.0.3 @apiGroup business @apiPermission registered user @apiDescription modified: change category type from string to number.<br/> modified: add name attribute.<br /> modified: change deal type from string to number.<br/> todo validation<br/> query string <br /> todo error / success return code in api <br /> @apiParam {Number=0, 25, 50, 100} [itemsPerPage=25] items for each request. @apiParam {Number} [page=1] page you want to request from, start with 1. @apiParam {String="name", "description"} [orderBy=name] the items order by column you specified. @apiParam {String="true", "false"} [desc=false] the items order by descending or asceding order. @apiExample {curl} Example usage: curl -X GET -H "mTag: xx" -H "Content-Type:application/json" -i http://localhost/rest/customer/businesses?itemsPerPage=50&page=1&orderBy=name&desc=true { "page":1, "type":"business", "orderBy":"name", "desc":0, "total":1, "itemsPerPage":25, "subtype":"list", "data":[ { "lat":120.678, "id":1, "deal":200, "name":"Starbucks Coffee 31", "image_url":"", "long":23.5383, "cat":1, "description":"early Bird Special: Get off." } ] } @apiSuccess {Number} total total items for pagination @apiSuccess {String} orderBy the items order by column you specified @apiSuccess {Number} page page you want to request from, start with 1 @apiSuccess {Number} itemsPerPage items for each request @apiSuccess {String} desc the items order by descending or asceding order @apiSuccess {String} type request's type @apiSuccess {String} subtype request's subtype @apiSuccess {Object} business object of business. @apiSuccess {Number} business.id item's uniq id. @apiSuccess {String} business.name item's name. @apiSuccess {Number} business.cat item's business industry category. @apiSuccess {float} business.lat item's entered latitude. @apiSuccess {float} business.long item's entered longitude. @apiSuccess {String} business.address item's address @apiSuccess {String} business.description item's description. @apiSuccess {Number} business.deal item's deal. @apiSuccess {String} business.image_url items's image url. @apiError CE_INVALID_PARAM invalid parameter HTTP/1.0 400 BAD REQUEST { "errorId": 2001, "message": "{'pages'}" } """ # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(field_inputs_wrap.keys()) requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 # one to many # 1. parsing reqest try: for k, v in field_inputs.items(): field_inputs[k]['required'] = False orgArgs, self.args = GetRequestArgs( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value # print(self.args, 'self.args', resource_fields_wrap) self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[field_inputs_wrap_head] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(obj, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') r = obj.query.filter(obj.isdel == False).order_by(isDesc()) _r = r.all() self.args['total'] = len(_r) if itemsPerPage is not 0: _r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() r = _r # 2. export to user for _r in r: __r = dict( (col, getattr(_r, col)) for col in _r.__table__.columns.keys()) #__r['description'] = getattr(_r.detail, 'description') # (1, 'icon'), (2, 'bg'), (3, 'gallery') ___r = pics.query.filter(pics.business_id == _r.id, pics.type == 1).scalar() __r['image_url'] = getattr(___r, 'path', "") self.args[field_inputs_wrap_head].append(__r) resource_fields_wrap[field_inputs_wrap_head] = fields.List( fields.Nested(resource_fields)) self.args['type'] = "business" self.args['subtype'] = "list" return marshal(self.args, resource_fields_wrap), 200
def get(self): """Get all data, getall @api {get} /rest/customer/comments list all comments @apiName GetAllCustomerComments @apiVersion 0.0.5 @apiGroup campaign @apiPermission registered user @apiDescription todo validation<br/> todo query target<br/> @apiParam {Number=0, 25, 50, 100} [itemsPerPage=25] items for each request. @apiParam {Number} [page=1] page you want to request from, start with 1. @apiParam {String} [orderBy=mtime] the items order by column you specified. @apiParam {String="true", "false"} [desc=false] the items order by descending or asceding order. @apiParam {String={..254}} [q] query string for pre-defined columns. @apiExample {curl} Example usage: curl -X GET -H "mTag: xx" -H "Content-Type:application/json" http://localhost/rest/customer/comments HTTP/1.0 200 OK { "page":1, "orderBy":"mtime", "desc":0, "total":2, "subtype":"comment", "type":"business", "itemsPerPage":25, "data":[ { "id":1, "business_id":1, "mtime":"2016-08-31 00:14:56.215613", "content":"Starbucks were all over Singapore and the quality ", "rate":2, "user":{ "id":2, "avatar_url":"" } }, { "id":2, "business_id":1, "mtime":"2016-08-31 04:23:15.682219", "content":"Starbucks were all over Singapore and the quality ", "rate":2, "user":{ "id":2, "avatar_url":"" } } ] } @apiSuccess {Number} total total items for pagination. @apiSuccess {String} orderBy the items order by column you specified. @apiSuccess {Number} page page you want to request from, start with 1. @apiSuccess {Number} itemsPerPage items for each request. @apiSuccess {String} desc the items order by descending or asceding order. @apiSuccess {Object[]} data List of business's comments. @apiSuccess {Number} data.id item's uniq id. @apiSuccess {String} data.content item's comment content @apiSuccess {Number} data.rate item's rate for business item @apiSuccess {Number} data.mtime items's latest modified time with ISO 8601 format @apiSuccess {Object} data.user item's author infomation @apiSuccess {Number} data.user.id item's author id @apiSuccess {String} data.user.avatar_url item's author avatar @apiError CE_INVALID_PARAM invalid parameter HTTP/1.0 400 BAD REQUEST { "errorId": 2001, "message": "{'pages'}" } @apiError CE_NOT_EXIST item not found HTTP/1.0 400 BAD REQUEST { "errorId": 2003, "message": "id 1 not found" } """ # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(field_inputs_wrap.keys()) requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 # one to many # 1. parsing reqest try: for k, v in field_inputs.items(): field_inputs[k]['required'] = False orgArgs, self.args = GetRequestArgs( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value # print(self.args, 'self.args', resource_fields_wrap) self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[field_inputs_wrap_head] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(obj, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') r = obj.query.filter(obj.isdel == False).order_by(isDesc()) _r = r.all() self.args['total'] = len(_r) if itemsPerPage is not 0: _r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() r = _r # 2. export to user for _r in r: __r = dict( (col, getattr(_r, col)) for col in _r.__table__.columns.keys()) ___r = db.session.query(Users).\ filter(_r.user_id == Users.id).scalar() __r['user'] = {'id': ___r.id, 'avatar_url': ___r.avatar_url} ___r = db.session.query(rates).\ filter(_r.user_id == rates.user_id, _r.business_id == rates.business_id).scalar() if ___r is not None: __r['rate'] = ___r.rate self.args[field_inputs_wrap_head].append(__r) _resource_fields = resource_fields.copy() _resource_fields_wrap = resource_fields_wrap.copy() _resource_fields['user'] = fields.Nested(resource_fields_user) _resource_fields_wrap[field_inputs_wrap_head] = fields.List( fields.Nested(_resource_fields)) self.args['type'] = "business" self.args['subtype'] = "comment" return marshal(self.args, _resource_fields_wrap), 200
def get(self, id): """get all devices info by business id @api {get} /rest/pushno/reg/:id registed devices under business id @apiVersion 0.0.4 @apiName GetAllDeviceByBusinessId @apiGroup pushno @apiPermission registered user @apiParam {Number} id business id, you can get from GetAllCustomerBusinesses. @apiDescription todo certificate with cookies / oauth 2.0<br /> todo long/lat validation<br /> todo metadata for counter of registerd devices<br /> todo error / success return code in api @apiExample {curl} Example usage: curl -X GET -H "mTag: xx" -H "Content-Type:application/json" http://localhost/rest/pushno/reg/1 { "orderBy":"user_id", "desc":0, "subtype":"reg", "itemsPerPage":25, "page":1, "data":[ { "dev_id":"eh2AM5l18K8:APA91bFsjAU_FmdkdTeErJ_BRSiz7_Iipi_r12QTscHciTVJmj1gcSK_p9l6BfgYtudntv0Ht7JNiyCe8lS-WdrL8zHOwCdGFdRutEDglPV1I9EeROVbhwVX0rcd_PS_jdCTQZ22inFq", "id":4, "user_id":1, "business_id":1, "type":1 }, { "dev_id":"eh2AM5l18K8:APA91bFsjAU_FmdkdTeErJ_BRSiz7_Iipi_r12QTscHciTVJmj1gcSK_p9l6BfgYtudntv0Ht7JNiyCe8lS-WdrL8zHOwCdGFdRutEDglPV1I9EeROVbhwVX0rcd_PS_jdCTQZ22inFq", "id":5, "user_id":1, "business_id":1, "type":1 }, { "dev_id":"eh2AM5l18K8:APA91bFsjAU_FmdkdTeErJ_BRSiz7_Iipi_r12QTscHciTVJmj1gcSK_p9l6BfgYtudntv0Ht7JNiyCe8lS-WdrL8zHOwCdGFdRutEDglPV1I9EeROVbhwVX0rcd_PS_jdCTQZ22inFq", "id":6, "user_id":1, "business_id":1, "type":1 } ], "total":3, "type":"pushno" } @apiSuccess {Number} total total items for pagination @apiSuccess {String} orderBy the items order by column you specified @apiSuccess {Number} page page you want to request from, start with 1 @apiSuccess {Number} itemsPerPage items for each request @apiSuccess {String} desc the items order by descending or asceding order @apiSuccess {String} type request's type @apiSuccess {Object[]} devices object of devices @apiSuccess {Number} devices.id device's uniq id @apiSuccess {Number} devices.user_id registered user id @apiSuccess {Number=1, 2}devices.type device's type, 1 for andriod, 2 for ios @apiSuccess {String{..254}} devices.dev_id device's id """ # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(field_inputs_wrap.keys()) requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 # one to many # 1. parsing reqest try: for k, v in field_inputs.items(): field_inputs[k]['required'] = False orgArgs, self.args = GetRequestArgs( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value # print(self.args, 'self.args', resource_fields_wrap) self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[field_inputs_wrap_head] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(obj, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') r = obj.query.filter(obj.business_id == id, obj.isdel == False).order_by(isDesc()) _r = r.all() self.args['total'] = len(_r) if itemsPerPage is not 0: _r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() r = _r # 2. export to user for _r in r: __r = dict( (col, getattr(_r, col)) for col in _r.__table__.columns.keys()) self.args[field_inputs_wrap_head].append(__r) _resource_fields = resource_fields.copy() _resource_fields_wrap = resource_fields_wrap.copy() _resource_fields_wrap[field_inputs_wrap_head] = fields.List( fields.Nested(_resource_fields)) self.args['type'] = "pushno" self.args['subtype'] = "reg" return marshal(self.args, _resource_fields_wrap), 200
} field_inputs_detail_rates['avatar_url'] = { 'validator': validate.str_range(argument={ 'low': 1, 'high': 255 }), 'type': fields.String() } field_inputs_detail['deals'] = { # type attribute for marshal 'type': { fields.List( fields.Nested({ 'title': { 'type': fields.String(attribute='title') }, 'description': { 'type': fields.String(attribute='description') }, })) }, # validate attribute for reqparse 'validator': { fields.List( fields.Nested({ 'title': { 'type': validate.str_range(argument={ 'low': 1, 'high': 64 }) },
def get(self, id): """Get all data, getall """ """get pics by business id @api {get} /rest/pic/gallery/:id get pictures list with business id @apiVersion 0.0.5 @apiName ListPicsUnderBusiness @apiGroup business @apiPermission registered user @apiDescription todo certificate with cookies / oauth 2.0<br /> todo long/lat validation<br /> todo metadata for counter of registerd devices<br /> todo error / success return code in api @apiParam {Number} id business id @apiExample {curl} Example usage: curl -X GET -H "mTag: xx" -H "Content-Type:application/json" http://localhost/rest/pic/gallery/1 { "orderBy":"id", "itemsPerPage":25, "subtype":"gallery", "desc":0, "data":[ { "path":"/img/customer/1/BYTPH2_20160618_6615.jpg", "id":5, "width":1024, "height":1365 }, { "path":"/img/customer/1/ZS0LII_10473.jpg", "id":6, "width":1024, "height":1365 }, { "path":"/img/customer/1/G30SLL_20160618_6615.jpg", "id":9, "width":1024, "height":1365 } ], "type":"pic", "total":3, "page":1 } @apiSuccess {Number} total total items in one business @apiSuccess {String} orderBy the items order by column you specified @apiSuccess {Number} page page you want to request from, start with 1 @apiSuccess {Number} itemsPerPage items for each request @apiSuccess {String} type request's type @apiSuccess {String} subtype request's subtype @apiSuccess {Object[]} data object @apiSuccess {Number} data.id image's id @apiSuccess {Number} data.path image's url that you could directly access @apiSuccess {Number} data.height image's height(px) @apiSuccess {Number} data.width image's width(px) """ # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(field_inputs_wrap.keys()) requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 # one to many # 1. parsing reqest try: for k, v in field_inputs.items(): field_inputs[k]['required'] = False orgArgs, self.args = GetRequestArgs( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value # print(self.args, 'self.args', resource_fields_wrap) self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[__heads__] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) #return omitError(ErrorMsg=repr(error)), 400 return omitError('CE_INVALID_PARAM', 'not found'), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(obj, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') # FIXME: use mapping table r = obj.query.filter(obj.type == 3, obj.business_id == id, obj.isdel == False).order_by(isDesc()) _r = r.all() self.args['total'] = len(_r) if itemsPerPage is not 0: _r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() r = _r # 2. export to user self.args[field_inputs_wrap_head] = [] for _r in r: __r = dict( (col, getattr(_r, col)) for col in _r.__table__.columns.keys()) # FIXME: use mapping table if __r['type'] == 3: rest_pic_prefix = os.path.join(REST_PIC_PREFIX, 'customer', str(__r['business_id'])) __r['path'] = os.path.join(rest_pic_prefix, __r['path']) self.args[field_inputs_wrap_head].append(__r) _resource_fields_wrap = resource_fields_wrap.copy() _resource_fields_wrap.pop('gallery_nr', None) _resource_fields_wrap[field_inputs_wrap_head] = fields.List( fields.Nested(resource_fields_post)) self.args['type'] = "pic" self.args['subtype'] = "gallery" return marshal(self.args, _resource_fields_wrap), 200
def post(self): """upload pics to business @api {post} /rest/pic/gallery upload multiple pictures to business @apiVersion 0.0.5 @apiName UploadPicsToBusiness @apiGroup business @apiPermission registered user @apiDescription todo certificate with cookies / oauth 2.0<br /> todo long/lat validation<br /> todo metadata for counter of registerd devices<br /> todo error / success return code in api @apiHeader {String} file[] upload file path @apiHeader {Number} business_id upload to business @apiHeader {String={customer}} type upload type @apiExample {curl} Example usage: curl -v -i -X POST -H "Content-Type: multipart/form-data" -F "file[]=@20160618_6615.jpg" -F "business_id=1" -F type="customer" -F "file[][email protected]" http://localhost/rest/pic/gallery { "type":"pic", "data":[ { "id":9, "path":"/img/customer/1/G30SLL_20160618_6615.jpg", "height":1365, "width":1024 }, { "id":10, "path":"/img/customer/1/3AZGA4_10473.jpg", "height":1365, "width":1024 } ], "page":1, "subtype":"gallery", "gallery_nr":2, "total":6 } @apiSuccess {Number} total total items in one business @apiSuccess {String} orderBy the items order by column you specified @apiSuccess {Number} page page you want to request from, start with 1 @apiSuccess {Number} gallery_nr current upload files number @apiSuccess {String} type request's type @apiSuccess {String} subtype request's subtype @apiSuccess {Object[]} data object @apiSuccess {Number} data.id image's id @apiSuccess {Number} data.path image's url that you could directly access @apiSuccess {Number} data.height image's height(px) @apiSuccess {Number} data.width image's width(px) """ try: orgArgs, self.args = GetTwoLayerRequestArgs( None, field_inputs, request.form) except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError('CE_INVALID_PARAM', 'not found'), 400 id = self.args['business_id'] type = self.args['type'] #print(self.args, 'self.args', id, type) #self.args = {} #id = request.form.get('business_id') #type = request.form.get('type') #if type not in PIC_ALLOWED_TYPE: # logger.debug('%s not in PIC_ALLOWED_TYPE', type) # type = None #if not id or not type: # return omitError('CE_INVALID_PARAM', 'id {} not found'.format(id)), 400 print("galleryed_files", request.files, "form data=", request.form) # 1. check id exist r = business.query.filter(business.id == id, business.isdel == False).scalar() if r is None: return omitError('CE_NOT_EXIST', 'id {} not found'.format(id)), 400 # if dir not exist, create it # /img/business/1/ pic_dir = os.path.join(STATIC_ROOT, PIC_PREFIX, type, str(id)) rest_pic_prefix = os.path.join(REST_PIC_PREFIX, type, str(id)) if not os.path.exists(pic_dir): os.makedirs(pic_dir) # TODO: review trigger time # 2. check last status that records are same with local _pics = [] count = 0 filenames = next(os.walk(pic_dir))[2] _filenames = filenames.copy() print("filenames=", _filenames) ps = obj.query.filter(obj.business_id == id).all() for v in ps: #print("filenames=", filenames, "v.path=", v.path) if v.path in filenames: count += 1 _filenames.remove(v.path) else: # prepare remove _pics.append(v) # TODO: need check duplicate record? # 2.1. commit to delete not relationship records try: for v in _pics: db.session.delete(v) db.session.flush() db.session.commit() except Exception as error: db.session.rollback() logger.warning('session commit error(%s)', error) return omitError(ErrorMsg=repr(error)), 400 # remove not exist db's file for v in _filenames: os.remove(os.path.join(pic_dir, v)) # 3. validate follows spec if count > max: return omitError('CE_EXCEED_LIMIT', 'limit is {}'.format(max)), 400 # 4. check pic name _pics = [] filenames = [] galleryed_files = request.files.getlist("file[]") print("galleryed_files file[]= ", galleryed_files) if len(galleryed_files) == 0: galleryed_files = request.files.getlist("customer") # for ios print("galleryed_files customer= ", galleryed_files) for file in galleryed_files: # Check if the file is one of the allowed types/extensions if file and self.allowed_file(file.filename): # Make the filename safe, remove unsupported chars filename = secure_filename(file.filename) print("file.filename=", file.filename, "filename=", filename) # Move the file form the temporal folder to the gallery # folder we setup p = obj() rs = ''.join( random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(6)) # 5FATMM_35e4183b.jpg.png -> 5FATMM_35e4183b.png extend = os.path.splitext(filename)[1] #print("self.remove_extend(filename)=", self.remove_extend(filename)) p.path = '_'.join([rs, self.remove_extend(filename)]) + extend p.business_id = id # (1, 'icon'), (2, 'bg'), (3, 'gallery') p.type = 3 _pics.append(p) filenames.append(filename) # 4. move to pic dir # FIXME: check file exist if abnormal error that db record save but pic not exist self.args[field_inputs_wrap_head] = [] path = [] _filenames = [] for k, v in enumerate(_pics): filename = os.path.join(pic_dir, filenames[k]) n_filename = os.path.join(pic_dir, v.path) try: # FIXME: handle <FileStorage: '35e4183b.jpg.png' ('application/octet-stream')>) galleryed_files[k].save(filename) #import shutil #shutil.copy(filename, n_filename) os.rename(filename, n_filename) _filenames.append(n_filename) print("n_filename = ", n_filename, "filename=", filename) img = Image.open(n_filename) s = img.size ratio = 0 v.width = s[0] v.height = s[1] if s[0] > MAXWIDTH: ratio = MAXWIDTH / s[0] v.width = MAXWIDTH v.height = int(round(s[1] * ratio)) img.thumbnail((v.width, v.height), Image.ANTIALIAS) print("img = ", img, "n_filenam=", n_filename, "format:", img.format, "width:", MAXWIDTH, ", height: ", int(round(s[1] * ratio)), "orgsize:", s) #img.save(n_filename, img.format) # FIXME: open 35e4183b.jpg.png error img.save(n_filename) except IOError: #for v in _filenames: # os.remove(v) return omitError('CE_IMAGE_RESIZE', 'image resize {} error'.format( filenames[k])), 400 # 5. commit to save try: for v in _pics: db.session.add(v) db.session.flush() db.session.refresh(r) for v in _pics: _pic = dict((col, getattr(v, col)) for col in v.__table__.columns.keys()) print("_pic:", _pic) _pic['path'] = os.path.join(rest_pic_prefix, v.path) self.args[field_inputs_wrap_head].append(_pic) db.session.commit() except Exception as error: db.session.rollback() logger.warning('session commit error(%s)', error) return omitError(ErrorMsg=repr(error)), 400 #output = {"type": "pic", "subtype": "gallery", # "imgs": {"total": count, "gallery_nr": len(_pics), "path": (path)}} for v in ['itemsPerPage', 'desc', 'orderBy']: resource_fields_wrap.pop(v, None) _resource_fields = {} resource_fields_wrap[field_inputs_wrap_head] = fields.List( fields.Nested(resource_fields_post)) self.args['total'] = len( obj.query.filter(obj.business_id == id, obj.isdel == False).all()) self.args['gallery_nr'] = len(_pics) self.args['type'] = "pic" self.args['subtype'] = "gallery" return marshal(self.args, resource_fields_wrap), 200