6

I spent last month learning Flask, and am now moving on to Pyramid and FastAPI. One of the requirements for my application is to get all the query parameters in a dictionary (there are multiple combinations, and I can assume all keys are unique and have a single value)

In Flask, for request like GET /?foo=1&bar=2 I can get the foo and bar parameters from a dictionary like this:

from flask import Flask, request
app = Flask(__name__)
@app.route("/")
def root():
     if 'foo' in request.args:
         return f"foo was provided: {request.args['foo']}", 200
     else:
         return "I need your foo, fool!", 400

I cannot figure out how to do the same easily in FastAPI / Starlette. Best solution I've come up with is to manually build the dictionary by splitting up request.query_params:

from fastapi import FastAPI, Request
app = FastAPI()

@app.get("/")
@app.get("/{path:path}")
def root(path, request: Request):

    request_args = {}
    if request.query_params:
        for _ in str(request.query_params).split("&"):
            [key, value] = _.split("=")
            request_args[key] = str(value)

It certainly seems there should be an easier way?

davidism
  • 121,510
  • 29
  • 395
  • 339
John Heyer
  • 711
  • 1
  • 6
  • 18
  • 1
    Does this answer your question? [URL query parameters to dict python](https://stackoverflow.com/questions/21584545/url-query-parameters-to-dict-python) – Glycerine May 04 '21 at 23:20
  • Why do you have two `@app.get` and why is your path `{path:path}`? – astrochun May 05 '21 at 02:44

2 Answers2

16

This is simple, just isn't documented very well. The Request class has an attribute called query_params. It's a mulitdict, but can easily be converted to a standard dictionary via the dict() function:

def root(path, req: Request):
    request_args = dict(req.query_params)
John Heyer
  • 711
  • 1
  • 6
  • 18
  • Indeed, `req.query_params` is perhaps the easiest way to get it. – astrochun May 07 '21 at 03:46
  • 2
    Be careful with blindly casting `request.query_params` to a dict. If you have, as the HTTP spec allows, multiple query parameters with the same key, it will only return the first key/value pair. Thus, `app?id=foo&id=bar` will only give you a dict with: `dict(req.query_params) => { 'id': 'foo' }` It's much safer to iterate through them, or re-parse as in https://stackoverflow.com/a/73831142/1183198 – bobmagoo Jan 04 '23 at 22:04
0

And to access any received JSON payload as dictionary (Flask-style, without the need to pre-define all dictionary keys), use the type hint Dict:

from fastapi import FastAPI
from typing import Any, Dict, List, Union

app = FastAPI()

@app.get("/")
async def root(path, request_dict: Union[List,Dict,Any]=None):
    return request_dict # a dict
mirekphd
  • 4,799
  • 3
  • 38
  • 59