-
-
Notifications
You must be signed in to change notification settings - Fork 8.5k
Description
Hi,
Description
I am looking to add an object or a dictionary to my endpoint.
There is an optional file in the request, so my understanding is that I need to use Form() fields.
Because there will be a lot of parameters to the endpoint, I would like to encapsulate related parameters in objects.
A simplified example would look like this:
class ThingDescription(BaseModel):
name: str
attribute1: str
attribute2: str
@app.post("/things")
async def create_thing(request: Request, background_tasks: BackgroundTasks, name: str = Form(...),
thing_description: Optional[ThingDescription] = Form(None),
data_file: Optional[UploadFile] = File(None),
current_user=Security(get_current_user, scopes=[Scopes.build.name])):I have tried requests using Swagger and the fastapi TestClient. Requests to this endpoint fail with validation errors.
I have tried to implement a Pydantic pre-validator, but it never gets called.
While troubleshooting, I used the debugger to break in fastapi dependencies\utils.py
v_, errors_ = field.validate(value, values, loc=loc)I see that the Pydantic validator does not convert a string to a dict. As a test, I converted the string to a dict and the request succeeded and the object was populated in my fastapi function.
import ast
v_, errors_ = field.validate(ast.eval_literal(value), values, loc=loc)This is where I hoped a Pydantic custom validator would help, but it doesn't seem to work as a pre-validator for the entire object.
My question is:
Is there a recommended way to do this?
Or, is it recommended that I simply list all those parameters on my endpoint?
Example
Here's a self-contained, minimal, reproducible, example with my use case:
from typing import Optional
from fastapi import FastAPI, Form, UploadFile, File
from pydantic import BaseModel
app = FastAPI()
class ThingDescription(BaseModel):
name: str
attribute1: str
attribute2: str
@app.post("/things")
async def create_solution(name: str = Form(...),
thing_description: Optional[ThingDescription] = Form(None),
data_file: Optional[UploadFile] = File(None)):
print(f'name: {name}')
if thing_description:
print(f'thing_description: {thing_description}')
if data_file:
print(f'filename: {data_file.filename}')
return {'status': 'success'}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000){
"detail": [
{
"loc": [
"body",
"thing_description"
],
"msg": "value is not a valid dict",
"type": "type_error.dict"
}
]
}Environment
- OS: Linux:
- FastAPI Version [e.g. 0.61.1]:
Thanks,
Tim