I am trying to pass comma separated query parameters to a Flask endpoint.
An example URI would be:
localhost:3031/someresource#?status=1001,1002,1003
Looking at the return of request.args
or request.args.getlist('status')
I see that I only get a string.
ipdb> pp request.args
ImmutableMultiDict([('status', '1001,1002,1003')])
ipdb> request.args.getlist('status')
['1001,1002,1003']
I know I can split the string by comma but that feels hacky. Is there a more idiomatic way to handle this in Flask? Or are my query params wrong format?
Solution
Since Flask does not directly support comma separated query params, I put this in in my base controller to support comma-separated or duplicate query params on all endpoints.
request_data = {}
params = request.args.getlist('status') or request.form.getlist('status')
if len(params) == 1 and ',' in params[0]:
request_data['status'] = comma_separated_params_to_list(params[0])})
else:
request_data['status'] = params
def comma_separated_params_to_list(param):
result = []
for val in param.split(','):
if val:
result.append(val)
return result
For GET requests, input can be specified only as query parameters, because a GET request cannot have a body. This example shows a GET request on the search resource, with two query parameters in the query string.
How do you pass a parameter in a python query? To send parameters in URL, write all parameter key:value pairs to a dictionary and send them as params argument to any of the GET, POST, PUT, HEAD, DELETE or OPTIONS request. then https://somewebsite.com/?param1=value1¶m2=value2 would be our final url.
request.args is a MultiDict with the parsed contents of the query string. From the documentation of get method: get(key, default=None, type=None) Return the default value if the requested data doesn't exist.
Its not uncommon REST API design to have commas to pass multiple values for the same key - makes it easier for the user. You're parsing GET args anyway, parsing strings is not that much more hacky. You can choose to raise a 400 HTTP error if their string with commas isn't well formatted.
Some other languages (notably PHP) support 'array' syntax, so that is used sometimes:
/request?status[]=1000&status[]=1001&status[]=1002
The flask
variant getlist
expects multiple keys:
from flask import Flask, request
app = Flask(__name__)
@app.route('/')
def status():
first_status = request.args.get("status")
statuses = request.args.getlist("status")
return "First Status: '{}'\nAll Statuses: '{}'".format(first_status, statuses)
❯ curl "http://localhost:5000?status=5&status=7"
First Status: '5'
All Statuses: '['5', '7']'
There's no standard for this, how multiple GET args are parsed/passed depends on which language/framework you're using; flask is built on werkzeug so it allows this style, but you'll have to look it up if you switch away from flask.
This is what you might want here:
request.arg.to_dict(flat=False)
flat
is True by default, so by setting it to False, you allow it to return a dict with values inside a list when there's more than one.
According to to_dict documentation:
to_dict(flat=True)
Return the contents as regular dict. If flat is True
the returned dict will only have the first item present, if flat is False
all values will be returned as lists.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With