def inner(self, *args, **kwargs): _default_size = default_size(self) \ if callable(default_size) else default_size _max_results = max_results(self) \ if callable(max_results) else max_results try: req = parser.parse( { 'page': fields.Int(validate=validate.Range(min=1), ), 'from': fields.Int( load_from='from', validate=validate.Range(min=1), ), 'size': fields.Int(validate=validate.Range(min=1), missing=_default_size), }, locations=['querystring'], validate=_validate_pagination_args, error_status_code=400, ) # For validation errors, webargs raises an enhanced BadRequest except BadRequest as err: raise SearchPaginationRESTError( description='Invalid pagination parameters.', errors=err.data.get('messages')) # Default if neither page nor from is specified if not (req.get('page') or req.get('from')): req['page'] = 1 if req.get('page'): req.update( dict(from_idx=(req['page'] - 1) * req['size'], to_idx=req['page'] * req['size'], links=dict( prev={'page': req['page'] - 1}, self={'page': req['page']}, next={'page': req['page'] + 1}, ))) elif req.get('from'): req.update( dict(from_idx=req['from'] - 1, to_idx=req['from'] - 1 + req['size'], links=dict( prev={'from': max(1, req['from'] - req['size'])}, self={'from': req['from']}, next={'from': req['from'] + req['size']}, ))) if req['to_idx'] > _max_results: raise SearchPaginationRESTError(description=( 'Maximum number of {} results have been reached.'.format( _max_results))) return f(self, pagination=req, *args, **kwargs)
class LivingResource(ProtectedResource, GrampsJSONEncoder): """Living calculator resource.""" @use_args( { "average_generation_gap": fields.Integer(missing=None, validate=validate.Range(min=1)), "max_age_probably_alive": fields.Integer(missing=None, validate=validate.Range(min=1)), "max_sibling_age_difference": fields.Integer(missing=None, validate=validate.Range(min=1)), }, location="query", ) def get(self, args: Dict, handle: Handle) -> Response: """Determine if person alive.""" db_handle = get_db_handle() person = get_person_by_handle(db_handle, handle) if person == {}: abort(404) data = probably_alive( person, db_handle, max_sib_age_diff=args["max_sibling_age_difference"], max_age_prob_alive=args["max_age_probably_alive"], avg_generation_gap=args["average_generation_gap"], ) return self.response(200, {"living": data})
class EndPoint(Resource): """ The EndPoint class is a flask endpoint resource used when the url path is /suggestions """ get_args = { "q": fields.Str(required=True), "latitude": fields.Float(required=False, validate=validate.Range(min=-90.0, max=90.0)), "longitude": fields.Float(required=False, validate=validate.Range(min=-90.0, max=90.0)), } def __init__(self, db): self.suggestion = Suggestion(db) @use_kwargs(get_args) def get(self, q, latitude=None, longitude=None): """ Return a suggestion of city(ies) depending of the query with a score depending of the match between the suggestion and what's in the database :param q: suggestion name :param latitude: latitude received from the suggestion ( optional ) :param longitude: longitude received from the suggestion ( optional ) :return: json """ logging.info('GET suggestions?q={}&latitude={}&longitude={}'.format( q, latitude, longitude)) return jsonify(self.suggestion.get(q, latitude, longitude))
def __init__(self): args = { 'location_id': fields.Int(allow_none=True), 'page': fields.Int(missing=1, validate=validate.Range(min=1)), 'per_page': fields.Int(missing=10, validate=validate.Range(min=1)), } parsed_args = parser.parse(args, request, location='querystring') self.location_id = parsed_args.get('location_id') self.page = parsed_args['page'] self.per_page = parsed_args['per_page']
class PortSchema(ma.Schema): cport = ma.Int( validate=validate.Range(min=0, max=65535) ) hport = ma.Int( required=True, validate=validate.Range(min=0, max=65535) ) proto = ma.Str( required=True, validate=validate.OneOf(['tcp','udp']) )
def __init__(self): args = { 'ids': fields.DelimitedList(fields.Int, allow_none=True), 'name': fields.Str(allow_none=True), 'page': fields.Int(missing=1, validate=validate.Range(min=1)), 'per_page': fields.Int(missing=10, validate=validate.Range(min=1)), } parsed_args = parser.parse(args, request, location='querystring') self.ids = parsed_args.get('ids') self.name = parsed_args.get('name') self.page = parsed_args['page'] self.per_page = parsed_args['per_page']
class FinishTransaction(Resource): args = { "transId": fields.Int(required=True, validate=validate.Range(min=1)), "resultNumber": fields.Int(required=True, validate=validate.Range(min=1)) } @use_kwargs(args) def put(self, transId, resultNumber): logger.info( "Calling /finishTransaction (PUT) with transId={}, resultNumber={}." .format(transId, resultNumber)) appDatabase.finishTransaction(transId, resultNumber)
def _get_pagination(self): limit_param_name = self.limit_param_name or current_app.config[ 'RESTLIB_URL_PARAM_LIMIT'] offset_param_name = self.offset_param_name or current_app.config[ 'RESTLIB_URL_PARAM_OFFSET'] pagination_schema = { limit_param_name: fields.Int(missing=current_app.config['RESTLIB_PAGINATION_LIMIT'], validate=validators.Range(min=1)), offset_param_name: fields.Int(missing=0, validate=validators.Range(min=0)), } pagination = parser.parse(pagination_schema, location='query') return pagination
class MallOrderCancellationView(MallBaseView): """商城-订单-取消订单""" @use_args( { "order_id": fields.Integer( required=True, validate=[validate.Range(1)], comment="订单ID") }, location="json", ) def put(self, request, args): customer_ids = list_customer_ids_by_user_id_interface( self.current_user.id) if not customer_ids: return self.send_fail(error_text="订单不存在") order = get_customer_order_by_id(customer_ids, args.get("order_id")) if not order: return self.send_fail(error_text="订单不存在") if order.order_status != OrderStatus.UNPAID: return self.send_fail(error_text="订单状态已改变") success, msg = cancel_order(order.shop_id, order.id) if not success: if order.order_type == OrderType.GROUPON: auto_validate_groupon_attend_interface(order.shop_id, order.groupon_attend) return self.send_fail(error_obj=msg) return self.send_success()
class AdminOrderFinishView(AdminBaseView): """后台-订单-完成订单""" @AdminBaseView.permission_required( [AdminBaseView.staff_permissions.ADMIN_ORDER]) @use_args( { "order_id": fields.Integer( required=True, validate=[validate.Range(1)], comment="订单ID") }, location="json", ) def post(self, request, args): shop_id = self.current_shop.id order = get_order_by_shop_id_and_id(shop_id, args.get("order_id")) if not order: return self.send_fail(error_text="订单不存在") elif order.order_status != OrderStatus.CONFIRMED: return self.send_fail(error_text="订单状态已改变") set_order_status_confirmed_finish( order, OrderStatus.FINISHED, self.current_user.id, OrderLogType.FINISH, ) # 获取店铺的消息提醒设置, 发送微信模板消息 msg_notify = get_msg_notify_by_shop_id_interface(shop_id) if msg_notify.order_finish_wx: order_finish_tplmsg_interface(order.id) return self.send_success()
class AdminOrderDirectView(AdminBaseView): """后台-订单-一键完成订单""" @AdminBaseView.permission_required( [AdminBaseView.staff_permissions.ADMIN_ORDER]) @use_args( { "order_id": fields.Integer( required=True, validate=[validate.Range(1)], comment="订单ID") }, location="json", ) def post(self, request, args): shop_id = self.current_shop.id order = get_order_by_shop_id_and_id(shop_id, args.get("order_id")) if not order: return self.send_fail(error_text="订单不存在") elif order.order_status != OrderStatus.PAID: return self.send_fail(error_text="订单状态已改变") # 创建一个配送记录 if order.delivery_method == OrderDeliveryMethod.HOME_DELIVERY: delivery_info = {"delivery_type": DeliveryType.StaffDelivery} delivery = create_order_delivery_interface(delivery_info) order.delivery_id = delivery.id set_order_status_confirmed_finish( order, OrderStatus.FINISHED, self.current_user.id, OrderLogType.DIRECT, ) msg_notify = get_msg_notify_by_shop_id_interface(shop_id) # if msg_notify.order_finish_wx: # order_finish_tplmsg_interface(order.id) return self.send_success()
class UpdateDog(Resource): """Resource serving PUT requests.""" args = { 'id': fields.Int( required=True, validate=validate.Range(min=1), ), } args.update(request_args) @use_args(args) def put(self, args): dog_id = args.get('id') dog = Dogs.query.filter_by(id=dog_id).first() if not dog: return {'error': 'Dog could not be found.'}, 404 try: for key, value in args.items(): setattr(dog, key, value) dog.save() # Delete all_dogs memcache as it is stale memcache_client.delete(ALL_DOGS) # update memcache with obj id. memcache_client.set(str(dog_id), dog.dict_repr(), expire=60) return dog.dict_repr(), 200 except SQLAlchemyError as exception_message: db.session.rollback() return {'error': str(exception_message)}, 403
class MallOrderPaymentView(MallBaseView): """商城-订单-支付""" @use_args( { "order_id": fields.Integer( required=True, validate=[validate.Range(1)], comment="订单ID"), "wx_openid": fields.String(required=True, comment="微信openID"), }, location="json", ) def put(self, request, args): customer_ids = list_customer_ids_by_user_id_interface( self.current_user.id) if not customer_ids: return self.send_fail(error_text="订单不存在") order = get_customer_order_by_id(customer_ids, args.get("order_id")) assert order.pay_type == OrderPayType.WEIXIN_JSAPI if not order: return self.send_fail(error_text="订单不存在") elif order.order_status != OrderStatus.UNPAID: return self.send_fail(error_text="订单状态已改变") success, params = jsapi_params_interface(order, args["wx_openid"]) if not success: return self.send_fail(error_obj=params) return self.send_success(data=params)
class AdminStaffListView(AdminBaseView): """后台-员工-员工列表""" pagination_class = StandardResultsSetPagination @AdminBaseView.permission_required( [AdminBaseView.staff_permissions.ADMIN_STAFF]) @use_args( { "keyword": fields.String(required=False, comment="搜索关键字(姓名或手机号)"), "page": fields.Integer(required=False, missing=1, comment="页码"), "page_size": fields.Integer(required=False, missing=20, validate=[validate.Range(1)], comment="每页条数"), }, location="query") def get(self, request, args): page = args.get("page") shop_id = self.current_shop.id staff_list = list_staff_by_shop_id(shop_id, args.get("keyword")) # page为-1时,不分页 if page > 0: staff_list = self._get_paginated_data(staff_list, StaffSerializer) else: # 适配前端参数要求 staff_list = { 'results': StaffSerializer(staff_list, many=True).data } return self.send_success(data_list=staff_list)
def __init__(self): args = { 'keyword': fields.Str(), 'page': fields.Int(missing=1, validate=validate.Range(min=1)), 'per_page': fields.Int(missing=10, validate=validate.Range(min=1)), 'plan_trigger_time': fields.DelimitedList(fields.DateTime()), 'status': fields.Int(), 'task_ids': fields.DelimitedList(fields.Int()), } parsed_args = parser.parse(args, request, location='querystring') self.count = parsed_args['per_page'] self.keyword = parsed_args.get('keyword') self.plan_trigger_time = parsed_args.get('plan_trigger_time') self.start = (parsed_args['page'] - 1) * parsed_args['per_page'] self.status = parsed_args.get('status') self.task_ids = parsed_args.get('task_ids')
class EventSpanResource(ProtectedResource, GrampsJSONEncoder): """Event date span resource.""" @property def db_handle(self) -> DbReadBase: """Get the database instance.""" return get_db_handle() @use_args( { "as_age": fields.Boolean(missing=True), "locale": fields.Str(missing=None, validate=validate.Length(min=1, max=5)), "precision": fields.Integer(missing=2, validate=validate.Range(min=1, max=3)), }, location="query", ) def get(self, args: Dict, handle1: Handle, handle2: Handle) -> Response: """Get the time span between two event dates.""" try: event1 = self.db_handle.get_event_from_handle(handle1) event2 = self.db_handle.get_event_from_handle(handle2) except HandleError: abort(404) locale = get_locale_for_language(args["locale"], default=True) span = (Span(event1.date, event2.date).format(precision=args["precision"], as_age=args["as_age"], dlocale=locale).strip("()")) return self.response(200, {"span": str(span)})
class FinishPrintMessage(Resource): args = { "messageId": fields.Int(required=True, validate=validate.Range(min=1)) } @use_kwargs(args) def put(self, messageId): logger.info("Calling /finishPrintMessage (PUT).") appDatabase.finishPrintMessage(messageId)
class MintTokenSchema(BaseSchema): to = AddressField(required=True) value = IntegerToStringField(required=True, validate=validate.Range(min=1, max=UINT256_MAX)) class Meta: strict = True decoding_class = dict
class InitPrintMessage(Resource): args = { "messageId": fields.Int(required=True, validate=validate.Range(min=1)), "messageText": fields.Str(required=True) } @use_kwargs(args) def put(self, messageId, messageText): logger.info("Calling /initPrintMessage (PUT).") appDatabase.initPrintMessage(messageId, messageText)
class MintTokenSchema(BaseSchema): to = AddressField(required=True) value = fields.Integer(required=True, validate=validate.Range(min=1, max=UINT256_MAX)) contract_method = fields.String(validate=validate.OneOf( choices=("increaseSupply", "mint", "mintFor"))) class Meta: strict = True decoding_class = dict
class ModifiableSettingsSchema(BaseSchema): """This is the Schema for the settings that can be modified via the API""" premium_should_sync = fields.Bool(missing=None) include_crypto2crypto = fields.Bool(missing=None) anonymized_logs = fields.Bool(missing=None) submit_usage_analytics = fields.Bool(missing=None) ui_floating_precision = fields.Integer( strict=True, validate=validate.Range( min=0, max=8, error= 'Floating numbers precision in the UI must be between 0 and 8', ), missing=None, ) taxfree_after_period = TaxFreeAfterPeriodField(missing=None) balance_save_frequency = fields.Integer( strict=True, validate=validate.Range( min=1, error= 'The number of hours after which balances should be saved should be >= 1', ), missing=None, ) include_gas_costs = fields.Bool(missing=None) # TODO: Add some validation to this field historical_data_start = fields.String(missing=None) # TODO: Add some validation to this field # even though it gets validated since we try to connect to it eth_rpc_endpoint = fields.String(missing=None) main_currency = FiatAssetField(missing=None) # TODO: Add some validation to this field date_display_format = fields.String(missing=None) class Meta: strict = True # decoding to a dict is required by the @use_kwargs decorator from webargs decoding_class = dict
class SuperShopVerifyView(UserBaseView): """总后台-修改店铺认证状态""" @use_args( { "sign": fields.String(required=True, comment="加密认证"), "timestamp": fields.Integer(required=True, comment="时间戳"), "user_id": fields.Integer(required=True, comment="用户ID"), "shop_id": fields.Integer( required=True, validate=[validate.Range(1)], comment="店铺ID"), "verify_status": fields.Integer( required=True, validate=[ validate.OneOf([ ShopVerifyActive.YES, ShopVerifyActive.CHECKING, ShopVerifyActive.REJECTED, ]) ], comment="店铺认证状态", ), "verify_type": fields.Integer( required=True, validate=[ validate.OneOf( [ShopVerifyType.ENTERPRISE, ShopVerifyType.INDIVIDUAL]) ], comment="店铺认证类型,个人/企业", ), "verify_content": fields.String(required=True, validate=[validate.Length(0, 200)], comment="认证内容"), }, location="json") @SuperBaseView.validate_sign("sign", ("user_id", "timestamp")) def put(self, request, args): shop = get_shop_by_shop_id(args.pop("shop_id")) if not shop: return self.send_fail(error_text="店铺不存在") serializer = SuperShopVerifySerializer(shop, data=args) if not serializer.is_valid(): return self.send_error(error_message=serializer.errors, status_code=status.HTTP_400_BAD_REQUEST) serializer.save() return self.send_success()
class LivingDatesResource(ProtectedResource, GrampsJSONEncoder): """Living calculator dates resource.""" @use_args( { "average_generation_gap": fields.Integer(missing=None, validate=validate.Range(min=1)), "locale": fields.Str(missing=None, validate=validate.Length(min=1, max=5)), "max_age_probably_alive": fields.Integer(missing=None, validate=validate.Range(min=1)), "max_sibling_age_difference": fields.Integer(missing=None, validate=validate.Range(min=1)), }, location="query", ) def get(self, args: Dict, handle: Handle) -> Response: """Determine estimated birth and death dates.""" db_handle = get_db_handle() locale = get_locale_for_language(args["locale"], default=True) person = get_person_by_handle(db_handle, handle) if person == {}: abort(404) data = probably_alive_range( person, db_handle, max_sib_age_diff=args["max_sibling_age_difference"], max_age_prob_alive=args["max_age_probably_alive"], avg_generation_gap=args["average_generation_gap"], ) profile = { "birth": locale.date_displayer.display(data[0]), "death": locale.date_displayer.display(data[1]), "explain": data[2], "other": data[3], } return self.response(200, profile)
class MallBrowseRecord(MallBaseView): """商城-创建浏览记录""" @register_browse_record("product") def gen_product_browse_record(self, args: dict): product_id = int(args["spa_params"]["product_id"]) product_ids = list_product_ids_by_shop_id_interface( self.current_shop.id, [ProductStatus.ON, ProductStatus.OFF] ) if product_id not in product_ids: return False, "货品不存在" info = { "shop_id": self.current_shop.id, "user_id": self.current_user.id, "product_id": product_id, "start_time": args["start_time"], "duration": args["duration"], "pre_page_name": args["pre_page"].get("name"), "next_page_name": args["next_page"].get("name"), } create_product_browse_record(info) return True, None @use_args( { "fullpath": fields.String( required=True, validate=[validate.Length(1, 256)], comment="url全路径" ), "query": StrToDict(required=True, comment="路由里面的query参数"), "cur_page": StrToDict(required=True, comment="当前页面, 包含type, name2个值, str"), "pre_page": StrToDict(required=True, comment="上一个页面, 包含type, name2个值, str"), "next_page": StrToDict(required=True, comment="下一个页面, 包含type, name2个值, str"), "spa_query": StrToDict(required=True, comment="当前页面的一些参数"), "spa_params": StrToDict(required=True, comment="当前页面的一些参数"), "start_time": fields.DateTime(required=True, comment="进入当前页面的时间"), "duration": fields.Integer( required=True, validate=[validate.Range(0)], comment="在页面停留的时间" ), }, location="json" ) def post(self, request, args, shop_code): self._set_current_shop(request, shop_code) # 暂时只记录商品的访问记录, 以后再扩展 cur_page_type = args["cur_page"]["type"] gen_browse_record_func = _MAP_BROWSE_RECORD[cur_page_type] success, info = gen_browse_record_func(self, args) if not success: return self.send_fail(error_text=info) return self.send_success()
async def dateadd( request: Request, addend: fields.Int(required=True, validate=validate.Range(min=1)), unit: fields.Str(missing="days", validate=validate.OneOf(["minutes", "days"])), value: dt.date = None, ) -> Response: """A datetime adder endpoint.""" value = value or dt.datetime.utcnow() if unit == "minutes": delta = dt.timedelta(minutes=addend) else: delta = dt.timedelta(days=addend) result = value + delta return JSONResponse({"result": result.isoformat()})
class AdminOrderRefundView(AdminBaseView): """后台-订单-退款""" @AdminBaseView.permission_required( [AdminBaseView.staff_permissions.ADMIN_ORDER]) @use_args( { "order_id": fields.Integer( required=True, validate=[validate.Range(1)], comment="订单ID"), "refund_type": fields.Integer( required=True, validate=[ validate.OneOf([ OrderRefundType.WEIXIN_JSAPI_REFUND, OrderRefundType.UNDERLINE_REFUND, ]) ], ), }, location="json", ) def post(self, request, args): shop_id = self.current_shop.id order = get_order_by_shop_id_and_id(shop_id, args.get("order_id")) if not order: return self.send_fail(error_text="订单不存在") elif order.order_status not in [ OrderStatus.PAID, OrderStatus.CONFIRMED, OrderStatus.FINISHED, OrderStatus.REFUND_FAIL, ]: return self.send_fail(error_text="订单状态已改变") if (order.pay_type == OrderPayType.ON_DELIVERY and args["refund_type"] == OrderRefundType.WEIXIN_JSAPI_REFUND): return self.send_fail(error_text="货到付款的订单只能进行线下退款") success, msg = refund_order( self.current_shop.id, order, args["refund_type"], self.current_user.id, ) if not success: return self.send_fail(error_obj=msg) # 获取店铺的消息提醒设置, 发送微信模板消息 msg_notify = get_msg_notify_by_shop_id_interface(shop_id) # if msg_notify.order_refund_wx and order.pay_type == OrderPayType.WEIXIN_JSAPI: # order_refund_tplmsg_interface(order.id) return self.send_success()
class ShopsDistResource(Resource): @use_args({ 'count': fields.Int(missing=20, location='query', validate=validate.Range(min=0)), 'dist': fields.Float(required=True, location='query', validate=validate.Range(min=0)), 'lng': fields.Float(required=True, location='query'), 'lat': fields.Float(required=True, location='query') }) def get(self, args, **_kwargs): dist = func.ST_Distance(Shop.position, from_shape(Point(args['lng'], args['lat']), srid=4326), True). \ label('dist') query = db.session.query(Shop, Shop.position, dist).options( lazyload('prices'), lazyload('tags')).filter(dist < 1000 * args['dist']).order_by( dist.asc()).limit(args['count']) shops = query.all() return ShopDistSchema().dump(shops, many=True).data
class AdminConfigReceiptCopiesView(AdminBaseView): """后台-设置-小票设置-小票底部信息设置""" @AdminBaseView.permission_required( [AdminBaseView.staff_permissions.ADMIN_CONFIG]) @use_args( { "copies": fields.Integer(required=True, validate=[validate.Range(0, 5)], comment="默认打印份数") }, location="json") def put(self, request, args): args["brcode_active"] = int(args.get("brcode_active", 1)) shop_id = self.current_shop.id update_receipt_by_shop_id(shop_id, args) return self.send_success()
class FizzBuzz(Resource): # Create validation schema for params 'word' and 'max_value' args = { 'word': fields.Str(required=True, validate=validate.OneOf(['fizz', 'buzz', 'fizzbuzz'])), 'max_value': fields.Int(required=True, validate=validate.Range(min=1)), } # Assign divisor/s to each word per instructions word_values = {'fizz': [3], 'buzz': [5], 'fizzbuzz': [3, 5]} # access the params when we receive them in http GET @use_kwargs(args) def get(self, word, max_value): # Uncomment the code below to reject all requests that have # extra paramaters i.e. params if params other than 'word' or # 'max_value' are included, we return an error response # for param in request.args: # print(param) # if param not in self.args.keys(): # error_response() # initalize an empty array of numbers numbers = [] # loop from 1 to max_value for i in range(1, max_value + 1): # run the modulus calculation for the divisors given # our 'word' api value # if our max value is wholly divisible by our iterator # then we append it to the numbers array if any(i % n == 0 for n in self.word_values.get(word)): numbers.append(i) # return the response return jsonify({'status': 'ok', 'numbers': numbers}) # if 'word' or 'max_value' doesnt validate per the schema, # we use this decorator to return an error defined under # error_response() @parser.error_handler def handle_request_parsing_error(err): # We could also return a more descriptive response # abort(422, errors=err.messages) error_response()
class AdminGrouponAttendOrdersView(AdminBaseView): """后台-玩法-拼团-拼团参与详情-成员订单""" pagination_class = StandardResultsSetPagination @AdminBaseView.permission_required( [AdminBaseView.staff_permissions.ADMIN_PROMOTION]) @use_args( { "groupon_attend_id": fields.Integer( required=True, validate=[validate.Range(1)], comment="拼团参与ID"), }, location="query") def get(self, request, args): args["shop_id"] = self.current_shop.id order_list = list_order_by_groupon_attend_id_interface(**args) order_list = self._get_paginated_data(order_list, AdminOrdersSerializer) return self.send_success(data_list=order_list)