I have this model:
class Text(BaseModel):
id: str
text: str = None
class TextsRequest(BaseModel):
data: list[Text]
n_processes: Union[int, None]
So I want to be able to take requests like:
{"data": ["id": "1", "text": "The text 1"], "n_processes": 8}
and
{"data": ["id": "1", "text": "The text 1"]}.
Right now in the second case I get
{'data': [{'id': '1', 'text': 'The text 1'}], 'n_processes': None}
using this code:
app = FastAPI()
@app.post("/make_post/", response_model_exclude_none=True)
async def create_graph(request: TextsRequest):
input_data = jsonable_encoder(request)
So how can I exclude n_processes
here?
You can use exclude_none
param of dict() :
class Text(BaseModel):
id: str
text: str = None
class TextsRequest(BaseModel):
data: list[Text]
n_processes: Optional[int]
request = TextsRequest(**{"data": [{"id": "1", "text": "The text 1"}]})
print(request.dict(exclude_none=True))
Output:
{'data': [{'id': '1', 'text': 'The text 1'}]}
Also, it's more idiomatic to write Optional[int]
instead of Union[int, None]
Pydantic provides the following arguments for exporting models using the model.dict(...)
method:
exclude_unset
: whether fields which were not explicitly set when creating the model should be excluded from the returned dictionary; defaultFalse
exclude_none
: whether fields which are equal to None should be excluded from the returned dictionary; defaultFalse
Since you are refering to excluding optional unset parameters, you can use the first method (ie, exclude_unset
). This is useful when one would like to exclude a parameter only if it has not been set to either some value or None
.
The exclude_none
argument, however, ignores that fact that an attribute may have been intentionally set to None
, and hence, excludes it from the returned dictionary.
Example:
from pydantic import BaseModel
from typing import List, Union
class Text(BaseModel):
id: str
text: str = None
class TextsRequest(BaseModel):
data: List[Text] # in Python 3.9+ you can use: data: list[Text]
n_processes: Union[int, None] = None
t = TextsRequest(**{'data': [{'id': '1', 'text': 'The text 1'}], 'n_processes': None})
print(t.dict(exclude_none=True))
#> {'data': [{'id': '1', 'text': 'The text 1'}]}
print(t.dict(exclude_unset=True))
#> {'data': [{'id': '1', 'text': 'The text 1'}], 'n_processes': None}
Using Union[int, None]
is the same as using Optional[int] = None
or int | None
int | None
(in Python 3.10+). However, as per FastAPI documentation (see admonition Note and Info in the link provided):
Note
FastAPI will know that the value of
q
is not required because of the default value= None
.The
Union
inUnion[str, None]
will allow your editor to give you better support and detect errors.
Info
Have in mind that the most important part to make a parameter optional is the part:
= None
, as it will use thatNone
as the default value, and that way make the parameter not required .The
Union[str, None]
part allows your editor to provide better support, but it is not what tells FastAPI that this parameter is not required .
Hence, regardless of the option (ie, Union
, Optional
, etc.) one may decide to use, if it is not followed by the = None
part, FastAPI won't know that the value of the parameter is not required , and hence, the user will have to provide some value for it. One can also check this through the auto-generated API docs at http://127.0.0.1:8000/docs , where the parameter
or request body
will appear as a Required
field.
For example:
@app.post("/upload")
def upload(t: Union[TextsRequest, None]):
def upload(t: Optional[TextsRequest]):
def upload(t: TextsRequest | None):
any of the above would require the user to pass some body for the TextsRequest
model in their request. If, however, the above TextsRequest
definitions were succeeded by = None
(eg, t: Union[TextsRequest, None] = None
, or even simply t: TextsRequest = None
), the parameter
or body
would be optional
(as = None
would tell FastAPI that this parameter is not required ).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.