简体   繁体   English

如何正确 map 用户定义的方法来获取/发布 HTTP 调用 Python Z9784E91C7B265789272?

[英]How to properly map user defined methods to GET/POST HTTP calls in Python Flask?

I am new to Python-Flask and trying to implement APIs in it.我是 Python-Flask 的新手,并试图在其中实现 API。 To do that, I have created two APIs which will receive the values and then display the values.为此,我创建了两个 API,它们将接收值然后显示值。 Code:代码:

from flask import Flask, jsonify, request
from flask_restful import Resource, Api, reqparse

app = Flask(__name__)
api = Api(app)

vehicles = []

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):
        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 vehicel {n} already exists in the database'.format(n=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

    def getallvehicles(self):
        return {'vehicles': vehicles}


api.add_resource(VehicleData, '/addvehicle/<string:name>', '/getvehicle/<string:name>', '/getallvehicles')
app.run(port=5000, debug=True)

Api Calls: Api 调用:

http://127.0.0.1:5000/addvehicle/polo
http://127.0.0.1:5000/getvehicle/polo
http://127.0.0.1:5000/getallvehicles

The calls to the methods POST and GET are working fine which can be seen in the image.POSTGET方法的调用工作正常,可以在图像中看到。 在此处输入图像描述

But when I run the third API which gives me all the entries of the list: vehicles , the code is giving an error saying it needs an argument name .但是当我运行第三个 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'

I understand that the GET call is invoking get() in the code and not getallvehicles() .我知道GET调用是在代码中调用get()而不是getallvehicles() Is it because getallvehicles is a user defined method?是因为getallvehicles是用户定义的方法吗? If so, could anyone let me know how to map a user defined method to GET or POST or any corresponding call.如果是这样,任何人都可以让我知道如何POST用户定义的方法来GET或发布或任何相应的调用。 In this case, how can I map getallvehicles to GET http call?在这种情况下,我如何 map getallvehicles来 GET http 调用?

Approach 1: I can add an extra class to the existing code & register in my API to return all the data from the list: vehicles方法 1:我可以在我的 API 中的现有代码和寄存器中添加额外的 class 以返回列表中的所有数据: vehicles

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

api.add_resource(GetAllVehicles, '/getallvehicles')

How can I achieve the same functionality without using an extra class in the code and map GET to getallvehicles()如何在代码中不使用额外的 class 和 map GET的情况下实现相同的功能getallvehicles()

Not exactly what you requested, but I would use a keyword 'all' as a possible input for getting all the vehicle data in the API.不完全符合您的要求,但我会使用关键字“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)

The modified code above returns all vehicles if the url /getvehicle/all is entered and prevents adding a car named 'all' in the post() function.如果输入了 url /getvehicle/all ,上面的修改后的代码将返回所有车辆,并防止在post() function 中添加名为“all”的汽车。

Not sure if I've fully understand your requirements but my interpretation is that you have three end-points:不确定我是否完全理解您的要求,但我的解释是您有三个端点:

  1. Add vehicle (loads data)添加车辆(加载数据)
  2. Get vehicle (gets the data of one of the vehicles based on an input)获取车辆(根据输入获取其中一辆车的数据)
  3. Get all vehicles (gets data for all of the vehicles)获取所有车辆(获取所有车辆的数据)

I would suggest storing the output in a nested dictionary as this makes it easier to manipulate.我建议将 output 存储在嵌套字典中,因为这样更容易操作。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM