Skip to main content

How to Parse Query Param With Multiple Values in FastAPI

·316 words·2 mins

In HTTP request, same query parameter with multiple values are allowed. For example, for query parameter brand, the query string looks like this: brand=foo&brand=bar. How to parse value of this parameter to a list in FastAPI? There are several different ways.

Using Type annotation and Query
#

If you already know which parameter is going to have multiple values, you can use the following method (based on discussion here):

from fastapi import FastAPI, Request, Query

app = FastAPI()

@app.get('/multi_value')
def multi_value(brand: List[str] = Query(default=None)):
    return {"brand": brand}

In this way, the query parameter brand will be known by FastAPI to have a list of values. If you access the API like this: http://127.0.0.1:8000/multi_value?brand=foo&brand=bar, you can get correct response:

{"brand":["foo","bar"]}

Deal with the request directly
#

If you do not know which parameter is going to have multiple values, you can also directly handle it with using the request object from FastAPI.

@app.get('/foo')
def foo(request: Request):
    query_params = request.query_params
    params_dict = {}
    for k in query_params.keys():
        params_dict[k] = query_params.getlist(k]
    return params_dict

If a query parameter can appear multiple time in the query, we shouldn’t use query_params.get() to get its values, because it will only return the last value. Similarly, query_params.items() and query_params.values() also only contain the last value for the query parameter.

Another way is to use parse_qs from urllib to parse the query string manually.

@app.get('/foo')
def foo(request: Request):
    # `request.url` is the complete URL for the HTTP request.
    # `request.url.query` contains only the query part from the whole URL. For example, if your complete
    # URL is http://127.0.0.1:8000/search2/foo?q=schuhe&color=blue&color=black, then the value for
    # request.url.query would be "q=schuhe&color=blue&color=black"
    params_dict = parse_qs(request.url.query, keep_blank_values=True)
    return params_dict

parse_qs() can handle parameter with several values correctly. It has a parameter keep_blank_values, if it is set to True, query parameter with no value will also be kept in the parsed result, and the corresponding value is set to an empty string.