After adding a dependency to parameter without changing the data format old requests stopped working with error: "422 Unprocessable Entity"
import requests
from fastapi import Depends, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str = None
price: float
tax: float = None
class User(BaseModel):
username: str
full_name: str = None
def dependant(item: Item):
return {'username': 'username', 'full_name': 'full_name'}
@app.post("/items/{item_id}")
def update_item(item_id: int, user: User, item: Item): #User = Depends(dependant)):
results = {"item_id": item_id, "item": item, "user": user}
return results
import requests
sample_body = {
"item": {
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
},
"user": {
"username": "dave",
"full_name": "Dave Grohl"
}
}
print(requests.post('http://localhost:2000/items/1', json=sample_body))
@app.post("/items/{item_id}")
def update_item(item_id: int, user: User, item: Item): #User = Depends(dependant)):
results = {"item_id": item_id, "item": item, "user": user}
return results
to
@app.post("/items/{item_id}")
def update_item(item_id: int, user: User, item: User = Depends(dependant)):
results = {"item_id": item_id, "item": item, "user": user}
return results
I expected, that the change would not affect input format, because the only difference is in internal processing. Also, auto documentation suggests the same.


@AIshutin
Hi! Well, I'm not sure that this particular case has been clearly described in the docs, but you're actually looking for this page. As described there, FastAPI will expect your model to be the root for the JSON body being sent if this model is the only model defined on the route (or dependency in your second case). In the first case, you have already defined 2 models on the same route, so FastAPI will expect them as separate fields in JSON.
You can change FastAPI behavior with Body parameter. In your case, you should be interested in the embed argument, which tells FastAPI that the model should be expected as a JSON field and not the whole body.
So, if you change your application to this, then everything should work:
from fastapi import Depends, FastAPI, Body
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str = None
price: float
tax: float = None
class User(BaseModel):
username: str
full_name: str = None
def dependant(item: Item = Body(..., embed=True)):
return {"username": "username", "full_name": "full_name"}
@app.post("/items/{item_id}")
def update_item(
item_id: int, user: User = Body(..., embed=True), item: User = Depends(dependant)
):
results = {"item_id": item_id, "item": item, "user": user}
return results
Big thanks! You helped a lot.
Thanks for the help here @nsidnev ! :cake: :bowing_man:
Thanks @AIshutin for reporting back and closing the issue :+1:
Most helpful comment
@AIshutin
Hi! Well, I'm not sure that this particular case has been clearly described in the docs, but you're actually looking for this page. As described there,
FastAPIwill expect your model to be the root for the JSON body being sent if this model is the only model defined on the route (or dependency in your second case). In the first case, you have already defined 2 models on the same route, soFastAPIwill expect them as separate fields in JSON.You can change
FastAPIbehavior withBodyparameter. In your case, you should be interested in theembedargument, which tellsFastAPIthat the model should be expected as a JSON field and not the whole body.So, if you change your application to this, then everything should work: