Query string arguments are values added at the end of the URL which follow the format of name1=value1&name2=value2. You can separate multiple values with an ampersand (as shown). The query string arguments are separated from the main part of the URL by a question mark.

So a complete URL with query string arguments might look like this:

http://your-api.com/item/?tag=furniture

To get multiple values, you'd include two or more of the same query string argument:

http://your-api.com/item/?tag=furniture&tag=office

In my REST APIs with Flask and Python course, we build REST APIs using the Flask-Smorest library. In this blog post, let me show you how to use query string arguments together with Flask-Smorest.

If you'd rather watch a video instead, check it out here:

How to access query string values in a Flask endpoint

Accessing the query string values in a Flask endpoint is relatively straightforward:

  • Import the request proxy from flask
  • Query string arguments are stored in a dict-like value under request.args.

Here's a sample endpoint that returns all the stores in your database.

@app.route("/store")
def get_stores():
    return [{"name": store.name, "id": store.id} for store in StoreModel.query.all()]

Now let's say you want to add a query string argument value to filter stores by name. Our API users will send us name=Tec, and the API should respond with stores whose name starts with Tec.

To get the query string argument value, we use request.args.get("name"):

# at top of file
from flask import app, request


# in endpoint
@app.route("/store")
def get_stores():
    name = request.args.get("name")
    return [{"name": store.name, "id": store.id} for store in StoreModel.query.all()]

Then we can add a filter to .query before calling .all():

# at top of file
from flask import request


# in endpoint
@app.route("/store")
def get_stores():
    name = request.args.get("name")
    return [
        {"name": store.name, "id": store.id}
        for store in StoreModel.query.filter(StoreModel.name.startswith(name)).all()
    ]

As an aside, if instead of .startswith you wanted to search for the given value anywhere in the store name, you could use this:

StoreModel.query.filter(StoreModel.name.like(f"%{name}%")).all()

Accessing a list of values in a query string argument

First, ensure the user is sending the query string like so:

?tags=furniture&tags=office

Then in Flask, access the values like so:

request.args.getlist("tags")  # ["furniture", "office"]

If you use request.args.get("tags"), then only the first tag value will be returned.

Alternatively, you could (but I don't recommend it), do this to work with comma-separated values:

request.args.get("tags").split(",")

The issue I can foresee with this is potentially if a value is received that contains a comma, you'd run into trouble. This probably wouldn't happen with tags, but it might happen with other values. You're better off using the recommended approach, which is getting multiple query string arguments and use .getlist().

How to access query string arguments in a Flask-Smorest Resource

Here's a sample Resource class that returns all the stores in your database. This is similar to the endpoint we showed earlier.

@blp.route("/store")
class StoreList(MethodView):
    @blp.response(200, StoreSchema(many=True))
    def get(self):
        return StoreModel.query.all()

Now you want to add the same query string argument as earlier, to filter the stores by name. You could simply do it as in vanilla Flask, by importing request and then using request.args.get().

But one of the key benefits of Flask-Smorest is the documentation and validation, so let's try to do better than that.

First we'll define a schema for our query string arguments:

class StoreSearchQueryArgs(BaseSchema):
    name: str | None

Then we decorate the get method with a @blp.arguments() decorator, making sure to pass location="query", like so:

@blp.route("/store")
class StoreList(MethodView):
    @blp.arguments(StoreSearchQueryArgs, location="query")
    @blp.response(200, StoreSchema(many=True))
    def get(self, search_values):
        return StoreModel.query.all()

Then we can add the filter to .query before calling .all():

@blp.route("/store")
class StoreList(MethodView):
    @blp.arguments(StoreSearchQueryArgs, location="query")
    @blp.response(200, StoreSchema(many=True))
    def get(self, search_values):
        return StoreModel.query.filter(StoreModel.name.startswith(search_values.get("name", ""))).all()

For a complete Flask-Smorest application that you can see in action, check out this Gist.

Alright, that's everything for this blog post! I just wanted to show you how to work with query string parameters in Flask, focusing on REST APIs with Flask-Smorest.

If you want to learn more about REST API development with Flask, consider looking at our course: REST APIs with Flask and Python. It's a complete video-course that covers everything you need, from the basics to working with databases, deployments, background tasks, and much more!