6

I want to handle a use case, where a key is passed to the GET request's query parameters, but without a value.

For example (request through Postman): Postman Request

In the case above, name is passed as a key but no value is set.

I tried using:

request.query_params

but, it doesn't seem to get the name, if the value is blank.

0

2 Answers 2

7

To retrieve query parameters from a request object, one could use request.query_params, which returns a starlette.datastructures.QueryParams object that is actually an ImmutableMultiDict with the query parameters. Another way is to use request.url.query, which returns the raw query string, as shown in this answer. Both approaches should also return keys with blank values in the query string.

Example

@app.get("/")
def main(request: Request):
    return request.query_params

Test URL

http://localhost:8000/?x=foo&y=bar&z=

Result

{"x":"foo","y":"bar","z":""}

One could retrieve values for specific keys the same way as in a standard dict:

x = request.query_params["x"]

As noted earlier, request.query_params would return an immutable multidict—one could confirm that by using print(type(request.query_params))—and thus, if one would like to convert the result into a standard dictionary, they could do that using the dict() function:

params = dict(request.query_params)

Note

In a scenario where you expect a list of values for a specific key, and may appear multiple times in the URL, using request.query_params or dict(request.query_params) to get a dictionary of every key-value pair in the query string wouldn't work as expected. For instance, /?foo=2&foo=10&bar=7 would return {"foo":"10","bar":"7"} instead of {"foo":["2","10"],"bar":"7"}. In that case, you may consider following an approach similar to this answer, using urllib.parse.parse_qs. In order to have keys with blank values included as well, you should set the keep_blank_values flag to True, as described in the documentation:

The optional argument keep_blank_values is a flag indicating whether blank values in percent-encoded queries should be treated as blank strings. A true value indicates that blanks should be retained as blank strings. The default false value indicates that blank values are to be ignored and treated as if they were not included.

Example

from fastapi import FastAPI, Request
from urllib.parse import parse_qs

app = FastAPI()

@app.get("/")
def main(request: Request):
    q_params = parse_qs(request.url.query, keep_blank_values=True)    
    d = dict((k, v if len(v)>1 else v[0]) 
                for k, v in q_params.items())

    return d

Test URL

http://localhost:8000/?foo=2&foo=10&bar=7&z=

Result

{"foo":["2","10"],"bar":"7","z":""}


On a side note, if the query parameters are known beforehand (not arbitrary) but not required, one could always declare them as Optional parameters in an endpoint (see Query Parameters documentation). Related answers on how to define query parameters in a FastAPI endpoint can be found here and here, as well as here and here.

Sign up to request clarification or add additional context in comments.

1 Comment

yeah, this seems the only way to properly deal with variable number of query parameters in the URL.
0

If you know that ?name is a possible URL query parameter that you might get without a value, you could declare it as optional in the handler function's parameter and then check for is not None. This example is adapted from the Optional parameters doc:

@app.get("/items/{item_id}")
async def read_item(item_id: str, name: str | None = None):
    if name is not None:
        return {"item_id": item_id, "name": True}
    return {"item_id": item_id}

NOTE: you have to declare it as str, not bool, since otherwise pydantic will raise a bool_parsing error, since bool args only allow for a limited set of values.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.