1

When making an app that uses dependency injection with a list field, the parameter automatically goes to the request body in SwaggerUI:

from fastapi import FastAPI, Query, Depends
import uvicorn
from pydantic import BaseModel, Field
from typing import List


class QueryParams(BaseModel):
    name: str = Field(...)
    ages: List[int] = Field([])


app = FastAPI()


@app.get("/test")
def test(query: QueryParams = Depends()):
    return "hi"

uvicorn.run(app)

SwaggerUI

Which means I cant test it in swagger UI. Even if I change field to query, it still doesn't work:

from fastapi import FastAPI, Query, Depends
import uvicorn
from pydantic import BaseModel, Field
from typing import List


class QueryParams(BaseModel):
    name: str = Field(...)
    ages: List[int] = Query([])  # <-- Query


app = FastAPI()


@app.get("/test")
def test(query: QueryParams = Depends()):
    return "hi"

uvicorn.run(app)

If I put it in the route function, it works:

from fastapi import FastAPI, Query, Depends
import uvicorn
from pydantic import BaseModel, Field
from typing import List


class QueryParams(BaseModel):
    name: str = Field(...)


app = FastAPI()


@app.get("/test")
def test(query: QueryParams = Depends(), ages: List[int] = Query([])):
    return "hi"

uvicorn.run(app)

Working UI

How can I get swagger UI to recognize a list query field in a basemodel with dependency injection?

Chris
  • 18,724
  • 6
  • 46
  • 80
Tom McLean
  • 5,583
  • 1
  • 11
  • 36

1 Answers1

1

As described in this answer, one can't use a List field inside a Pydantic model and expect it to be a query parameter. The way to do this is to implement your query parameter-parsing in a separate dependency class, as shown below:

class QueryParams:
    def __init__(
        self,
        name: str,
        ages: List[int] = Query(...)
    ):
        self.name = name
        self.ages = ages
        
@app.get("/test")
def test(query: QueryParams = Depends()):
    return "hi"

The above can be re-written using the @dataclass decorator, as shown below:

from dataclasses import dataclass

@dataclass
class QueryParams:
    name: str
    ages: List[int] = Query(...)

@app.get("/test")
def test(query: QueryParams = Depends()):
    return "hi"

Update

One could wrap the Query() in a Field() that would allow them to define a List field as query parameter inside the Pydantic model. A working example can be found in this answer.

Chris
  • 18,724
  • 6
  • 46
  • 80
  • Do you know why we cant use a query parameter in a base model for a list field? Is it a design decision? – Tom McLean Jul 21 '22 at 14:08
  • 1
    Could be. There is an extensive discussion [here](https://github.com/tiangolo/fastapi/issues/318), if you would like to have a look. – Chris Jul 21 '22 at 14:30