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

问题描述 投票:0回答:3

我有这个型号:

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
呢?

python fastapi pydantic optional-parameters
3个回答
5
投票
由于 Pydantic >= 2.0 弃用 model.dict(),请使用
model.model_dump(...)
代替。

您可以使用 Pydantic 的

model.dict(...)
:exclude_none

参数
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]
更惯用。


3
投票

Pydantic 提供了以下参数,用于使用

model.dict(...)
方法导出模型(Update:此方法最近已被
model.model_dump(...)
取代):

exclude_unset
:是否未显式设置的字段 创建模型应从返回的字典中排除; 默认
False

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

由于您指的是排除可选的 unset 参数,因此您可以使用第一种方法(即

exclude_unset
)。当人们想要排除某个参数时,这非常有用,only,如果它尚未设置为某个值或
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 文档(请参阅提供的链接中的警告 NoteInfo):

注意

FastAPI 会知道

q
的值不是必需的,因为 默认值
= None

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

信息

请记住,使参数可选的最重要部分 是部分:

= None
,因为它将使用
None
作为默认值,这样就可以使 参数非必填

Union[str, None]
部分可以让你的编辑器提供更好的 支持,但这并不是告诉FastAPI这个参数是 不需要

因此,无论您选择使用哪个选项,如果后面没有

= None
部分,FastAPI 将不知道该参数的值是 可选,因此,用户将 必须为其提供一些价值。您还可以通过 http://127.0.0.1:8000/docs 处自动生成的 API 文档进行检查,其中 parameter
request body
 将显示为 
Required
 字段。

例如,以下任何内容都会

要求用户在其对body

模型的请求中传递一些
TextsRequest
内容:

@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及更高版本中,您不必担心像Optional

Union
这样的名称,因为您可以简单地使用竖线
|
(也称为按位或运算符,但这个含义与这里无关)定义一个
可选
参数(或者简单地说,类型的联合)。 但是,相同的规则也适用于此选项,即,如果您想让参数可选,您仍然需要添加
= None
部分(如下面给出的示例所示)。 示例:

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



0
投票
response_model_exlclude_none

 代替 
response_model_exclude_unset
app = FastAPI()

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

© www.soinside.com 2019 - 2024. All rights reserved.