Svencken
Svencken

Reputation: 509

FastAPI: Using multiple dependencies (functions), each with pydantic request bodies

With FastAPI I am trying to inject two dependent functions, each of which have their own pydantic request bodies and form part of separate endpoints into path operation of another endpoint. Please see the example below just for illustration:

from fastapi import FastAPI, Depends
from pydantic import BaseModel

app = FastAPI()

class RequestBodyChild1(BaseModel):
    item1: float
    item2: float

class RequestBody1(BaseModel):
    parent1: RequestBodyChild1

@app.post("/function_1")
def function_1(request: RequestBody1):
    return request

class RequestBodyChild2(BaseModel):
    itemA: float
    itemB: float

class RequestBody2(BaseModel):
    parent2: RequestBodyChild2


@app.post("/function_2")
def function_2(request: RequestBody2):
    return request


@app.post("/function_3")
def function_3(request_1: dict = Depends(function_1), request_2: dict = Depends(function_2)):
    merged_dict = dict(request_1.items() + request_2.items())
    return merged_dict

The issue is that for the function_3 endpoint OpenAPI/Swagger only shows the request body/example schema for request_1: dict = Depends(function_1):

{
  "parent1": {
    "item1": 0,
    "item2": 0
  }
}

How can I make sure that both request bodies are included? Along the lines of:

{
  "parent1": {
    "item1": 0,
    "item2": 0
  },
  "parent2": {
    "itemA": 0,
    "itemB": 0
  }
}

Upvotes: 1

Views: 6335

Answers (1)

MatsLindh
MatsLindh

Reputation: 52892

The reason for the result you're seeing as that you're using the same parameter name in both functions - when you're using Depends in that way, the parameter name in the function is used (the function being registered as a view isn't relevant; only that it is a function); since it's the same in both cases, you only get a single argument name filled. You can see this change if you rename the parameter in function_2 to request2:

{
  "request": {
    "parent1": {
      "item1": 0,
      "item2": 0
    }
  },
  "request2": {
    "parent2": {
      "itemA": 0,
      "itemB": 0
    }
  }
}

To achieve the request format you've described I think you'd have to define the parent1: RequestBodyChild1, parent2: RequestBodyChild2 directly on function_3, and then call the dependent functions manually.

def function_3(parent1: RequestBodyChild1, parent2: RequestBodyChild2):
  ...

This resolves to:

{
  "parent1": {
    "item1": 0,
    "item2": 0
  },
  "parent2": {
    "itemA": 0,
    "itemB": 0
  }
}

Upvotes: 1

Related Questions