I am creating an API using Flask-RESTful, and am attempting to make a resource that returns all items in a database that are like a user defined string.
The endpoint for this resource is defined as:
api = Api(app) api.add_resource(ItemsList, '/privateapi/item?query=<string:tag>')
And the resource itself is:
class ItemsList(Resource): def get(self, tag): search = f"%{tag}%" items = ItemModel.query.filter(ItemModel.item_name.like(search)).all() return {"items": [item.json() for item in items]}
The problem is that when I send a GET request to the endpoint http://127.0.0.1:5000/privateapi/item?query=appl
I get a 404
response.
When I change the endpoint to api.add_resource(ItemsList, '/privateapi/item/<string:tag>')
and then query the API I get the desired response.
However, I would prefer to use the query approach since I am not trying to GET a single record but want to return an array. I just think it makes more sense this way.
What could I try?
Advertisement
Answer
In flask, query parameters aren’t used to match routes (only the path part of the URL is relevant). When you write:
api.add_resource(ItemsList, '/privateapi/item?query=<string:tag>')
You have created a route that will never match (well, not exactly; see below).
You access query parameters in the request.args
value, like this:
from flask import Flask, request from flask_restful import Resource, Api app = Flask(__name__) api = Api(app) class ItemsList(Resource): def get(self): query = request.args.get("query") return f"Query expression was: {query}" api.add_resource(ItemsList, "/privateapi/item") if __name__ == "__main__": app.run(debug=True)
With the above code, if I write:
curl http://127.0.0.1:5000/privateapi/item?query=appl
I get as the response:
"Query expression was: appl"
When I said “You have created a route that will never match” this was actually a bit of lie. In fact, you have created a route that requires a literal ?
in the URL path, so if you were to make a request for this URL:
curl http://127.0.0.1:5000/privateapi/item%3Fquery=appl
It would work, but it’s not what you want.