如何使用FastAPI从Pydantic模型中排除可选的未设置值



我有这个型号:

class Text(BaseModel):
id: str
text: str = None

class TextsRequest(BaseModel):
data: list[Text]
n_processes: Union[int, None]

所以我希望能够接受这样的请求:

{"data": ["id": "1", "text": "The text 1"], "n_processes": 8} 

{"data": ["id": "1", "text": "The text 1"]}.

现在在第二种情况下,我得到

{'data': [{'id': '1', 'text': 'The text 1'}], 'n_processes': None}

使用此代码:

app = FastAPI()
@app.post("/make_post/", response_model_exclude_none=True)
async def create_graph(request: TextsRequest):
input_data = jsonable_encoder(request)

那么,如何在此处排除n_processes

由于Pydantic>=2.0弃用model.dict((,改为使用model.model_dump(...)

您可以使用Pydantic模型的exclude_none参数。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))

输出:

{'data': [{'id': '1', 'text': 'The text 1'}]}

此外,编写Optional[int]而不是Union[int, None]更为惯用。

Pydantic为使用model.dict(...)方法导出模型提供了以下参数(Update:此方法最近已被model.model_dump(...)取代(:

exclude_unset:当创建模型应该从返回的字典中排除;默认False

exclude_none:等于None的字段是否应该从返回的词典中排除;默认False

由于您指的是排除可选的未设置参数,因此可以使用第一种方法(即exclude_unset(。如果要仅排除参数(如果该参数未设置为某个值或None(,则此选项非常有用。

然而,exclude_none参数忽略了一个事实,即属性可能已被有意设置为None,因此将其从返回的字典中排除。

示例:

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}

关于可选参数

使用Union[int, None]与使用Optional[int]是相同的(两者都是等效的(。然而,使参数可选的最重要的部分是= None部分。

根据FastAPI文档(请参阅提供的链接中的警告注意信息(:

注意

FastAPI将知道q的值不是必需的,因为默认值CCD_ 20。

Union[str, None]中的Union将允许您的编辑器为您提供更好地支持和检测错误。

信息

请记住,使参数可选的最重要部分是部分:= None,因为它将使用None作为默认值,这样就使得参数不是必需的

Union[str, None]部分允许您的编辑器提供更好的支持,但这不是告诉FastAPI该参数是不需要

因此,无论您选择使用哪个选项,如果后面没有= None部分,FastAPI都不会知道参数的值是可选的,因此,用户将必须为其提供一些值。您也可以通过http://127.0.0.1:8000/docs,其中parameterrequest body将显示为Required字段。

例如,以下任何一项都将要求用户在其对TextsRequest模型的请求中传递一些body内容:

@app.post("/upload")
def upload(t: Union[TextsRequest, None]):
pass
@app.post("/upload")
def upload(t: Optional[TextsRequest]):
pass

但是,如果上述TextsRequest定义被= None继承,例如:

@app.post("/upload")
def upload(t: Union[TextsRequest, None] = None):
pass
@app.post("/upload")
def upload(t: Optional[TextsRequest] = None):
pass

@app.post("/upload")
def upload(t: TextsRequest = None): # this should work as well
pass

参数(或主体(将是可选,因为= None将告诉FastAPI该参数是-不需要

在Python 3.10中+

好消息是,在Python 3.10及更高版本中,您不必担心OptionalUnion这样的名称,因为您可以简单地使用竖条|(也称为位或运算符,但这一含义在这里无关(来定义可选参数(或简单地说,类型的并集(但是,同样的规则也适用于此选项,即如果您想使参数可选,则仍然需要添加= None部分(如下面给出的示例所示(。

示例:

@app.post("/upload")
def upload(t: TextsRequest | None = None):
pass

您可以使用response_model_exclude_unset而不是response_model_exlclude_none

app = FastAPI()
@app.post("/make_post/", response_model_exclude_unset=True)
async def create_graph(request: TextsRequest):
input_data = jsonable_encoder(request)

最新更新