flask restful: passing parameters to GET request

140.2k views Asked by At

I want to create a resource that supports GET request in following way:

/bar?key1=val1&key2=val2

I tried this code, but it is not working

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

class BarAPI(Resource):
    def get(key1, key2):
        return jsonify(dict(data=[key1, key2]))

api.add_resource(BarAPI, '/bar', endpoint='bar')

Thanks!

4

There are 4 answers

2
Aditya On BEST ANSWER

Flask can parse arguments through request

from flask import request

You can use following lines in the block that requires GET parameters. GET is declared in @app.route() declaration.

args = request.args
print (args) # For debugging
no1 = args['key1']
no2 = args['key2']
return jsonify(dict(data=[no1, no2])) # or whatever is required
0
Paul Rooney On

Edit: reqparse is no longer the recommended way to do this with flask-restful!, but there is another example using marshmallow below.

The reqparse object is deprecated. See the docs or the second example in this post for alternatives.


Use reqparse. You can see another example in the flask-restful docs.

It performs validation on the parameters and does not require jsonify.

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

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

class BarAPI(Resource):
    def get(self):

        parser = reqparse.RequestParser()
        parser.add_argument('key1', type=str)
        parser.add_argument('key2', type=str)

        return parser.parse_args()

api.add_resource(BarAPI, '/bar', endpoint='bar')

if __name__ == '__main__':
    app.run(debug=True)

Another way is to use marshmallow.

You can use a Schema class,to validate request.args (for a PUT/POST request you might validate request.form)

from flask import Flask, request, abort
from flask_restful import Resource, Api
from marshmallow import Schema, fields


class BarQuerySchema(Schema):
    key1 = fields.Str(required=True)
    key2 = fields.Str(required=True)

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


class BarAPI(Resource):
    def get(self):
        errors = schema.validate(request.args)
        if errors:
            abort(400, str(errors))

        return 'ok'

api.add_resource(BarAPI, '/bar', endpoint='bar')

# omit of you intend to use `flask run` command
if __name__ == '__main__':
    app.run(debug=True)

This example requires that both parameters be present.

0
Hung On

The answer of @severen is from 2016 and a bit outdated with regards to webargs. As i understand it, with the major update to 6.0.0 (in 2020), the decorator looks at the json payload by default and disregards the parameters within the query. To add this hint, add location="query" to the decorator (see github issue ).

Taking the example above, a working Endpoint which accepts a GET request would look like this:

class Foo(Resource):
    @use_kwargs({"bar": fields.Str(), }, location="query")
    def get(self, bar):
        return {'message': 'Hello, ' + bar}, 200
0
severen On

Since reqparse is deprecated, here is a solution using the WebArgs library:

from flask import Flask
from flask_restful import Api, Resource, abort
from webargs import fields, validate
from webargs.flaskparser import use_kwargs, parser

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

class Foo(Resource):
    args = {
        'bar': fields.Str(
            required=True,
            validate=validate.OneOf(['baz', 'qux']),
        ),
    }

    @use_kwargs(args)
    def get(self, bar):
        return {'bar': bar}

api.add_resource(Foo, '/foo', endpoint='foo')

# This error handler is necessary for usage with Flask-RESTful.
@parser.error_handler
def handle_request_parsing_error(err, req, schema, *, error_status_code, error_headers):
    abort(error_status_code, errors=err.messages)

if __name__ == '__main__':
    app.run(debug=True)

For more examples, see the Flask-RESTful example in the WebArgs repository.