What is the correct way to handle queries for a Flask RESTful endpoint?

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?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x