如何在Python中正确映射用户定义的方法以获取/发布HTTP调用?

如何在Python中正确映射用户定义的方法以获取/发布HTTP调用?,python,flask,Python,Flask,我不熟悉Python Flask,并尝试在其中实现API。 为此,我创建了两个API,它们将接收值,然后显示值。 代码: 对方法POST和GET的调用工作正常,如图所示。 但是当我运行第三个API时,它提供了列表中的所有条目:vehicles,代码给出了一个错误,表示它需要一个参数name Traceback (most recent call last): File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.

我不熟悉Python Flask,并尝试在其中实现API。 为此,我创建了两个API,它们将接收值,然后显示值。 代码:

对方法
POST
GET
的调用工作正常,如图所示。

但是当我运行第三个API时,它提供了列表中的所有条目:
vehicles
,代码给出了一个错误,表示它需要一个参数
name

Traceback (most recent call last):
  File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.7/site-packages/flask/app.py", line 2464, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.7/site-packages/flask/app.py", line 2450, in wsgi_app
    response = self.handle_exception(e)
  File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.7/site-packages/flask_restful/__init__.py", line 272, in error_router
    return original_handler(e)
  File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.7/site-packages/flask/app.py", line 1867, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.7/site-packages/flask/_compat.py", line 38, in reraise
    raise value.with_traceback(tb)
  File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.7/site-packages/flask/app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.7/site-packages/flask/app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.7/site-packages/flask_restful/__init__.py", line 272, in error_router
    return original_handler(e)
  File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.7/site-packages/flask/app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.7/site-packages/flask/_compat.py", line 38, in reraise
    raise value.with_traceback(tb)
  File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.7/site-packages/flask_restful/__init__.py", line 468, in wrapper
    resp = resource(*args, **kwargs)
  File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.7/site-packages/flask/views.py", line 89, in view
    return self.dispatch_request(*args, **kwargs)
  File "/Users/bobby/PyCharmProjects/FlaskAPI/venv/lib/python3.7/site-packages/flask_restful/__init__.py", line 583, in dispatch_request
    resp = meth(*args, **kwargs)
TypeError: get() missing 1 required positional argument: 'name'
我知道
GET
调用调用的是代码中的
GET()
,而不是
getallvehicles()
。 是因为
getallvehicles
是用户定义的方法吗?如果是这样的话,谁能告诉我如何将用户定义的方法映射到
GET
POST
或任何相应的调用。在这种情况下,如何映射
getallvehicles
以获取http调用

方法1: 我可以向现有代码中添加一个额外的类,并在API中注册以返回列表中的所有数据:
vehicles

class GetAllVehicles(Resource):
    
    def get(self):
        return {'vehicles': vehicles}

api.add_resource(GetAllVehicles, '/getallvehicles')

如何在不使用代码中的额外类的情况下实现相同的功能,并将
GET
映射到
getallvehicles()

不完全符合您的要求,但我会使用关键字“all”作为获取API中所有车辆数据的可能输入

class VehicleData(Resource):

    parser = reqparse.RequestParser()
    parser.add_argument('vehicle', type=str, required=True, help='name cannot be empty')
    parser.add_argument('type', type=str, required=True, help='vehicle type cannot be empty')
    parser.add_argument('wheels', type=int, required=True, help='number of wheels cannot be empty')
    parser.add_argument('suv', type=bool, required=False, help='SUV or not can be empty')

    def get(self, name):
        if name == 'all': # return all vehicles if 'all' keyword is passed
            return {'vehicles': vehicles}
        else:
            vehicle = list(filter(lambda x: x['name'] == name, vehicles), None)
            return {'vehicle': vehicle}, 200 if vehicle else 404

    def post(self, name):
        # data = request.get_json()
        # sport.append({'sportname': data['sport_name'], 'team_size':data['team_size'], 'popularity':data['popularity']})
        if next(filter(lambda x: x['name'] == name, vehicles), None) is not None:
            print("in the IF BLOCK")
            return {'message': 'The vehicle {n} already exists in the database'.format(n=name)}, 404
        elif name == 'all': # prevent adding a vehicle named 'all'
            return {'message': 'Invalid vehicle name'}, 404

        v_data = VehicleData.parser.parse_args()
        vehicle = {'name': name, 'type':v_data['type'],  'vehicle': v_data['vehicle'], 'suv': v_data['suv'], 'wheels': v_data['wheels']}
        vehicles.append(vehicle)
        return vehicle, 201

api.add_resource(VehicleData, '/addvehicle/<string:name>', '/getvehicle/<string:name>')
app.run(port=5000, debug=True)
class车辆数据(资源):
parser=reqparse.RequestParser()
parser.add_参数('vehicle',type=str,required=True,help='name不能为空')
parser.add_参数('type',type=str,required=True,help='vehicle type不能为空')
parser.add_参数('wheels',type=int,required=True,help='wheels的数量不能为空')
parser.add_参数('suv',type=bool,required=False,help='suv or not可以为空')
def get(自我,名称):
如果name==“all”:#如果传递了“all”关键字,则返回所有车辆
返回{'vehicles':车辆}
其他:
车辆=列表(过滤器(λx:x['name']==名称,车辆),无)
返回{'vehicle':vehicle},如果车辆为404,则返回200
def post(自我,姓名):
#data=request.get_json()
#追加({'sportname':数据['sport\u name'],'team\u size':数据['team\u size'],'popularity':数据['popularity']})
如果next(过滤器(λx:x['name']==名称,车辆),None)不是None:
打印(“在IF块中”)
返回{'message':'vehicle{n}已存在于数据库中。'format(n=name)},404
elif name=='all':#禁止添加名为'all'的车辆
返回{'message':'Invalid vehicle name'},404
v_data=VehicleData.parser.parse_args()
车辆={'name':名称,'type':车辆数据['type'],'vehicle':车辆数据['vehicle'],'suv':车辆数据['suv'],'wheels':车辆数据['wheels']}
车辆。附加(车辆)
返回车辆,201
api.add_资源(VehicleData,“/addvehicle/”,“/getvehicle/”)
运行(端口=5000,调试=True)

如果输入了url
/getvehicle/all
,上面修改的代码将返回所有车辆,并阻止在
post()
函数中添加名为“all”的车辆。

不确定我是否完全理解您的要求,但我的解释是您有三个端点:

  • 添加车辆(装载数据)
  • 获取车辆(根据输入获取其中一辆车辆的数据)
  • 获取所有车辆(获取所有车辆的数据)
  • 我建议将输出存储在嵌套字典中,因为这样更易于操作

    from flask import Flask, request
    
    global vehicles
    vehicles = {}
     
    my_app = Flask(__name__)
    
    @my_app.route('/load_vehicle', methods=['POST'])
    def load_vehicle():
    
        """
        Example JSON:
            
        {'compass':{'type':'car',
                    'vehicle':'automobile',
                    'suv':True,
                    'wheels':4}}
        """
    
        global vehicles
        
        json_in = request.get_json(silent=True)
    
        if json_in != None:
            
            vehicles.update(json_in)
    
    
    @my_app.route('/get_vehicle', methods=['POST'])
    def get_vehicle():
    
        """
        Example JSON:
            
        {'name':'compass'}
        """
    
        global vehicles
        
        json_in = request.get_json(silent=True)
    
        if json_in != None:
            
            output = vehicles[json_in['name']]
    
        return output
    
    @my_app.route('/get_all', methods=['GET'])
    def get_all():
        
        global vehicles
        
        return vehicles
    
    

    好啊代码中方法的名称是GET/PUT/POST等。我面临的错误是getallvehicles(),这是我给出的名称。我无法在类VehicleData中使用GET、PUT或POST来映射它。希望我现在明白了。是的,这是因为GET调用正在调用GET()。实现方法的唯一方法是使用一个新类将“/getallvehicles”映射到或扩展“get”方法。请参阅:该主题来自2013年,我使用的是Flask的最新版本。我想我现在不能用这个。
    class VehicleData(Resource):
    
        parser = reqparse.RequestParser()
        parser.add_argument('vehicle', type=str, required=True, help='name cannot be empty')
        parser.add_argument('type', type=str, required=True, help='vehicle type cannot be empty')
        parser.add_argument('wheels', type=int, required=True, help='number of wheels cannot be empty')
        parser.add_argument('suv', type=bool, required=False, help='SUV or not can be empty')
    
        def get(self, name):
            if name == 'all': # return all vehicles if 'all' keyword is passed
                return {'vehicles': vehicles}
            else:
                vehicle = list(filter(lambda x: x['name'] == name, vehicles), None)
                return {'vehicle': vehicle}, 200 if vehicle else 404
    
        def post(self, name):
            # data = request.get_json()
            # sport.append({'sportname': data['sport_name'], 'team_size':data['team_size'], 'popularity':data['popularity']})
            if next(filter(lambda x: x['name'] == name, vehicles), None) is not None:
                print("in the IF BLOCK")
                return {'message': 'The vehicle {n} already exists in the database'.format(n=name)}, 404
            elif name == 'all': # prevent adding a vehicle named 'all'
                return {'message': 'Invalid vehicle name'}, 404
    
            v_data = VehicleData.parser.parse_args()
            vehicle = {'name': name, 'type':v_data['type'],  'vehicle': v_data['vehicle'], 'suv': v_data['suv'], 'wheels': v_data['wheels']}
            vehicles.append(vehicle)
            return vehicle, 201
    
    api.add_resource(VehicleData, '/addvehicle/<string:name>', '/getvehicle/<string:name>')
    app.run(port=5000, debug=True)
    
    from flask import Flask, request
    
    global vehicles
    vehicles = {}
     
    my_app = Flask(__name__)
    
    @my_app.route('/load_vehicle', methods=['POST'])
    def load_vehicle():
    
        """
        Example JSON:
            
        {'compass':{'type':'car',
                    'vehicle':'automobile',
                    'suv':True,
                    'wheels':4}}
        """
    
        global vehicles
        
        json_in = request.get_json(silent=True)
    
        if json_in != None:
            
            vehicles.update(json_in)
    
    
    @my_app.route('/get_vehicle', methods=['POST'])
    def get_vehicle():
    
        """
        Example JSON:
            
        {'name':'compass'}
        """
    
        global vehicles
        
        json_in = request.get_json(silent=True)
    
        if json_in != None:
            
            output = vehicles[json_in['name']]
    
        return output
    
    @my_app.route('/get_all', methods=['GET'])
    def get_all():
        
        global vehicles
        
        return vehicles