Pydantic model inside model with file request body in FastApi

22 views Asked by At

I'm having issues using a Pydantic model inside another one along with a file in the request body.

Here is my endpoint definition:

async def download_process_videos_csv(
    db: get_db_session,
    payload: ProcessVideoPayload = Depends(),
    file: UploadFile = File(...),
    force: bool = False,
) -> JSONResponse:

where ProcessVideoPayload is defined as follows:

class GenerateVideoModelInfo(BaseModel):
    """Mode setup for the video processing task."""

    ml_model_class: str = "movinet"
    ml_model_name: str = "a2"

    ids: list[int] = [214]
    input_start: int = 0
    input_end: int | None = None
    batch_size: int = 32
    sequence_size: int = 1
    use_precomputed_pickle: bool = False
    video_length: int = 60
    combine_videos: bool = True
    peaks_per_video: int = 1


class ProcessVideoPayload(BaseModel):
    """The base request payload for process video endpoints."""

    folder_name: str = "input_videos"
    ml_model_setup: GenerateVideoModelInfo = GenerateVideoModelInfo()

This is how my Swagger UI looks (I'm using default values defined in Pydantic models, and I'm just uploading test.csv):

enter image description here

But when executing, I'm getting an error "Input should be a valid dictionary or object to extract fields from.":

{
  "detail": [
    {
      "type": "model_attributes_type",
      "loc": [
        "body",
        "ml_model_setup"
      ],
      "msg": "Input should be a valid dictionary or object to extract fields from",
      "input": "{\r\n  \"ml_model_class\": \"movinet\",\r\n  \"ml_model_name\": \"a2\",\r\n  \"ids\": [\r\n    214\r\n  ],\r\n  \"input_start\": 0,\r\n  \"batch_size\": 32,\r\n  \"sequence_size\": 1,\r\n  \"use_precomputed_pickle\": false,\r\n  \"video_length\": 60,\r\n  \"combine_videos\": true,\r\n  \"peaks_per_video\": 1\r\n}",
      "url": "https://errors.pydantic.dev/2.6/v/model_attributes_type"
    }
  ]
}

Is there a way to make it work? When I use the same Pydantic model in another endpoint but without a file in the request body like this:

@router.post("/download_process_video", status_code=201)
async def download_process_video(
    db: get_db_session, payload: ProcessVideoPayload, force: bool = False
) -> JSONResponse:

It works without any issues. I would like to keep this ProcessVideoPayload structure as I need both endpoints with and without uploading a file and I'm using the payload.ml_model_setup as input for some function.

0

There are 0 answers