First check
Example
Here's a self-contained minimal, reproducible, example with my use case:
from fastapi import APIRouter, Depends, FastAPI, Query
from fastapi.responses import JSONResponse
from typing import List, Optional
from pydantic import BaseModel, Field
import uvicorn
class MyModelData1(BaseModel):
archive: Optional[str] = Field(None, description="Archive name")
archive_type: Optional[str] = Field(None, description="Archive type")
class MetadataGet(BaseModel):
id: Optional[str] = Field(None, alias="_id")
foreign_key: Optional[str] = Field(None, alias="_foreign_key")
class DeepNestedModelGet(BaseModel):
name: Optional[str]
version: Optional[str]
class DetailsModelGet(BaseModel):
some_data: Optional[List[Optional[DeepNestedModelGet]]]
some_data2: Optional[List[Optional[str]]]
class MyModelData2(BaseModel):
id: Optional[str] = Field(None, alias="_id")
details: Optional[DetailsModelGet]
meta: Optional[MetadataGet]
def get_documents(collection, sort_by, sort_order, page, page_size, **additional_filters):
return {
"collection": collection,
}
app = FastAPI()
router1 = APIRouter(prefix="/data1", tags=["Data1"])
router2 = APIRouter(prefix="/data2", tags=["Data2"])
@router1.get("/", description="Retrieve all documents.")
def get_data1(
sort_by: str = Query(None, description="Sort by this field"),
sort_order: str = Query(None, description="Sort order"),
page: int = Query(1, description="Page number"),
page_size: int = Query(100, description="Number of documents per page"),
params: MyModelData1 = Depends(),
):
document = get_documents(
"data1",
sort_by,
sort_order,
page,
page_size,
**params.model_dump()
)
return JSONResponse(content=document)
@router2.get("/")
def get_data2(
sort_by: str = Query(None, description="Sort by this field"),
sort_order: str = Query(None, description="Sort order"),
page: int = Query(1, description="Page number"),
page_size: int = Query(100, description="Number of documents per page"),
params: MyModelData2 = Depends(),
):
"""Get all software."""
document = get_documents(
"data2",
sort_by,
sort_order,
page,
page_size,
**params.model_dump(),
)
return JSONResponse(content=document)
app.include_router(router1)
app.include_router(router2)
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=5000)
Description
- Open the browser and call the GET endpoint
/data1/.
- No request body is required for the GET method
- Open the browser and call the GET endpoint
/data2/.
- A request body is required for the GET method and provided
- If the user does not delete the request body since it is invalid a
TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body. is returned.
The solution you would like
The request body is not a required part of the GET /data2/ UI documentation when using an identical Depends() structure so dump_model() method can be used to pass very large models to the documentation as query parameters for the GET method which are optional.
Environment
- OS: Linux
- FastAPI Version: 0.109.0
- Python version: 3.9.18
Additional context
I've gone so far as to take List[str] which became Optional[List[str] in the Get version of the model, to an extreme of Optional[List[Optional[str]]] and List[DetailsModelGet] which was already all optional fields into Optional[List[Optional[DetailsModelGet]]]. Pushing Optional down to the last type and making "deeply optional" fields in case somehow this would resolve the issue. I cannot seem to find any instance of how to get the nested models not to result in a required request body in the docs GET method except to remove the nested (optional) models entirely and use a single-layer Pydantic model.
Originally posted by @stevesuh in #7275
First check
Example
Here's a self-contained minimal, reproducible, example with my use case:
Description
/data1/./data2/.TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body.is returned.The solution you would like
The request body is not a required part of the GET
/data2/UI documentation when using an identicalDepends()structure sodump_model()method can be used to pass very large models to the documentation as query parameters for the GET method which are optional.Environment
Additional context
I've gone so far as to take
List[str]which becameOptional[List[str]in the Get version of the model, to an extreme ofOptional[List[Optional[str]]]andList[DetailsModelGet]which was already all optional fields intoOptional[List[Optional[DetailsModelGet]]]. Pushing Optional down to the last type and making "deeply optional" fields in case somehow this would resolve the issue. I cannot seem to find any instance of how to get the nested models not to result in a required request body in the docs GET method except to remove the nested (optional) models entirely and use a single-layer Pydantic model.Originally posted by @stevesuh in #7275