17

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!

Omkar Neogi
  • 675
  • 2
  • 9
  • 30
  • What exactly is it you want to accomplish? Why do you need multiple parameters? – Luis Orduz Jan 04 '18 at 12:55
  • I am creating a REST API modeling tradingview.com - you make a GET request asking for charts related to a stock's price. If you want a regression line drawn over the stock price data, you mention it in the "class" variable like so: 'class=regr'. Say you also wanted the MACD - a type of analysis tool like regression - then you would also pass in 'class=macd'. The GET Request would thus become: http://localhost:5000/item/analysis=true&class=macd&class=regr/ – Omkar Neogi Jan 04 '18 at 12:58

2 Answers2

22

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 !

JahMyst
  • 1,616
  • 3
  • 20
  • 39
  • 2
    I ended up using `parser.add_argument('analysis', type=str,...` and then your `TRUTHY` approach as even when I pass `curl http://localhost:5000/item -G -d "class=A,B" -d "analysis=False"` the `if analysis: print("yeah")` will print `yeah`. So i am not sure how to process the Boolean output correctly; it seems to evaluate to `True` once something is passed. – Cleb Oct 09 '18 at 19:50
  • If you use the flask_restful input.boolean it should work properly: `from flask_restful import inputs` and then: `add_argument('analysis', type=inputs.boolean, default=False, required=False, help='Enable analysis')` – sevenam Jun 05 '19 at 10:39
-2

The query string cannot be use that way.

It will be overwritten, so just use a string such as:

class=A,B
hcoat
  • 2,633
  • 1
  • 22
  • 29
CheStar
  • 3
  • 2