Accepting multiple parameters in flask-restful add_resource()

Omkar Neogi picture Omkar Neogi · Jan 4, 2018 · Viewed 12.5k times · Source

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!

Answer

JahMyst picture JahMyst · Jan 5, 2018

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 !