For some reason handling Form
Data and File
Upload at the same time raises an error.
from typing import Annotated
from pydantic import BaseModel, StringConstraints, EmailStr
class RouteBody(BaseModel):
email: Annotated[EmailStr, StringConstraints(
max_length = 255
)]
password: Annotated[str, StringConstraints(
max_length = 60
)]
And this enforces that the routes body is correct. Super nice.
from fastapi import UploadFile, File
@some_api_router.post("/some-route")
async def handleRoute(routeBody: RouteBody = Form(), profilePicture: UploadFile = File(...)):
return {"msg": "Route"}
And I test it out using SwaggerUI docs:
I get the following error:
error [{'type': 'model_attributes_type', 'loc': ('body', 'routeBody'), 'msg': 'Input should be a valid dictionary or object to extract fields from', 'input': '{"email":"[email protected]","password":"string"}'}]
- Tested it out on a separate route without the "RouteBody" and it worked perfectly.
- Rewrote Route Handler from Scratch
- Changed the order of the parameters (don't know why I thought this mattered ... maybe it did?)
- Instead of using a Pydantic Model type for the RouteBody, I opted for individual parameters to make it functional. However, this isn’t an ideal solution, as it requires listing out all the parameters if you have many of them.
- Asked ChatGPT for guidance
routeBody: RouteBody = json.loads(Form())
– Heliopolisclass RouteBody(BaseModel):
– Heliopolispydantic_core._pydantic_core.SchemaError: Invalid Schema: model.config.extra_fields_behavior Input should be 'allow', 'forbid' or 'ignore' [type=literal_error, input_value='form', input_type=str] For further information visit https://errors.pydantic.dev/2.9/v/literal_error
– ClementclementasTypeError: the JSON object must be str, bytes or bytearray, not Form
– Clementclementas(routeBody: RouteBody = Form()
if you replace RouteBody with str, your code should work, so you need to work on how to make data from Form validate in your pydantic model – HeliopolisrouteBody: RouteBody = Form(embed=True)
– HeliopolisFile
, but ratherForm
data (defined in a Pydantic model) along with someFile
. What they experience is actually true - just tested it (their solution below, though, is not correct). To me, this seems to be a bug with Swagger/OpenAPI, and should be brought to FastAPI's creator attention (i.e., @tiangolo). It should be possible for one to define a Pydantic model forForm
attributes, and aFile
as well in the endpoint, but Swagger for some reason interprets theForm
attributes as JSON instead, when theFile
is included. – WundtFile
and JSON data instead, one should take a look at this answer – Wundt