Search code examples
pythonflaskflask-restful

Accepting multiple parameters in flask-restful add_resource()


I want to handle a GET request in my Flask REST API. The request will include multiple parameters, and you can expect this to be a typical GET request: https://localhost:5000/item/analysis=true&class=A&class=B

Thus, a GET request consists of:

  1. a Boolean variable called "analysis"
  2. a list called "class"

I want to accept this inside an add_resource() as follows:

add_resource(Item, '/item/<whatever-comes-here>')

I am clueless about how I would accept multiple parameters (one of them being a list) inside the add_resource(). How do I accept them in the add_resource() function and how do I unpack them inside the get() function?

I have spent time reverse engineering this, but I have not yet been successful. Am I doing something wrong?

(I understand that there might be a better way to send lists with a REST API GET request, so I'd appreciate any pointers regarding that!) Sincere thanks in advance!


Solution

  • URL parameters are defined after ? so your URL should be instead:

    https://localhost:5000/item?analysis=true&class=A&class=B

    You don't have to specify anything in add_resource for such URL parameters.

    You can just get the parameters from Flask's request proxy object in your API GET method:

    from flask import Flask, request
    from flask_restful import Api, Resource
    
    app = Flask(__name__)
    api = Api(app)
    
    # Flask mishandles boolean as string
    TRUTHY = ['true', 'True', 'yes']
    
    class Item(Resource):
       def get():
          # Get `class` list from request args
          classes = request.args.getlist('class') 
    
          # Get `analysis` boolean from request args
          analysis = True if request.args.get('analysis') in TRUTHY else False
    
    api.add_resource(Item, '/item')
    

    For more flexibility in the parameters you can receive, you can use Flask Restful's own request parser as described here to parse the request.

    The code becomes:

    from flask import Flask
    from flask_restful import Api, Resource, reqparse
    
    app = Flask(__name__)
    api = Api(app)
    
    # Define parser and request args
    parser = reqparse.RequestParser()
    parser.add_argument('class', type=list)
    parser.add_argument('analysis', type=bool, default=False, required=False, help='Enable analysis')
    
    class Item(Resource):
       def get():
           args = parser.parse_args()
           classes = args['class']  # List ['A', 'B']
           analysis = args['analysis'] # Boolean True
    
    api.add_resource(Item, '/item')
    

    Finally, sometimes a more compact format for a list might be desired (for example limit in url size), in which case I often use a comma separated list: https://localhost:5000/item?analysis=true&class=A,B

    and in the request parser, just accept it like a string and split it on ',':

    parser.add_argument('class', type=str)
    ...
    classes = args['class'].split(',')
    

    Cheers !