fastapi
fastapi copied to clipboard
Make exclude_unset work in pydantic models dependencies in form body
First Check
- [X] I added a very descriptive title to this issue.
- [X] I used the GitHub search to find a similar issue and didn't find it.
- [X] I searched the FastAPI documentation, with the integrated search.
- [X] I already searched in Google "How to X in FastAPI" and didn't find any information.
- [X] I already read and followed all the tutorial in the docs and didn't find an answer.
- [X] I already checked if it is not related to FastAPI but to Pydantic.
- [X] I already checked if it is not related to FastAPI but to Swagger UI.
- [X] I already checked if it is not related to FastAPI but to ReDoc.
Commit to Help
- [X] I commit to help with one of those options 👆
Example Code
from fastapi import Depends, Form, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
x: str = Form()
@app.get("/")
async def foo(item: Item = Depends()):
print(item.dict(exclude_unset=True))
Description
Open the browser and call endpoint "/"
It prints {}
Wanted Solution
I would like it not to fill dependency model with nulls, but leave it unset, with a parameter in Depends for backward compatibilty
Wanted Code
from fastapi import Depends, Form, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
x: str = Form()
@app.get("/")
async def foo(item: Item = Depends(leave_unset=True)):
print(item.dict(exclude_unset=True))
Alternatives
Make Form() in fields in models work without Depends() in handler function. Right now it is considered as application/json
Operating System
Windows
Operating System Details
Windows 11
FastAPI Version
0.78.0
Python Version
3.10.6
Additional Context
No response
are you want to access http://localhost:8000/
with parameter unset?
are you want to access
http://localhost:8000/
with parameter unset?
I want to access it with parameter unset and in this case the print be {} instead of {"x": None} as it is now
Open the browser and call endpoint "/" It prints {}
And
I want to access it with parameter unset and in this case the print be {} instead of {"x": None} as it is now
Seem to be the opposite of each other..
Open the browser and call endpoint "/" It prints {}
And
I want to access it with parameter unset and in this case the print be {} instead of {"x": None} as it is now
Seem to be the opposite of each other..
Really? May be I don't construct my sentences correctly. It seems perfectly same to me... What I mean is: now it prints {"x": None}, but I want it to print {} (because exclude_unset is True and "x" wasn't passed in request)
I see. You could use exclude_none=True
like so:
class Item(BaseModel):
x: str | None = Form()
@app.get("/")
async def foo(item: Item = Depends()):
print(item.dict(exclude_unset=True, exclude_none=True))
This would print {}
as the default value is None
. Not exactly the same you were trying to achieve but maybe might work in your specific use case? It would mean that you would not allow null
values as a valid input in certain Form()
fields.
I see. You could use
exclude_none=True
like so:class Item(BaseModel): x: str | None = Form() @app.get("/") async def foo(item: Item = Depends()): print(item.dict(exclude_unset=True, exclude_none=True))
This would print
{}
as the default value isNone
. Not exactly the same you were trying to achieve but maybe might work in your specific use case? It would mean that you would not allownull
values as a valid input in certainForm()
fields.
I know about exclude_none, but that's not exactly what I wanted. That's different things
It looks like I have similar problem, so...
I have this schema:
class GetStatisticsQueries(BaseModel):
match_id: int | None = None
game_id: int | None = None
statistics_type: StatisticsType | None = None
And I want to use it as query parameters schema this way:
@router.get(
'',
summary='Get statistics by the given fields',
response_model=list[StatisticsSchema],
)
async def get_statistics(
queries: GetStatisticsQueries = Depends(),
...
) -> list[dict]:
queries_dict = queries.dict(exclude_unset=True)
The problem is that dict(exclude_unset=True)
returns all values every time even if value was not set. I guess it happens because of Depends()
call.