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

lde*_*ina 10 python optional-parameters pydantic fastapi

我有这个模型:

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


class TextsRequest(BaseModel):
    data: list[Text]
    n_processes: Union[int, None]
Run Code Online (Sandbox Code Playgroud)

所以我希望能够接受如下请求:

{"data": ["id": "1", "text": "The text 1"], "n_processes": 8} 
Run Code Online (Sandbox Code Playgroud)

{"data": ["id": "1", "text": "The text 1"]}.
Run Code Online (Sandbox Code Playgroud)

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

{'data': [{'id': '1', 'text': 'The text 1'}], 'n_processes': None}
Run Code Online (Sandbox Code Playgroud)

使用此代码:

app = FastAPI()

@app.post("/make_post/", response_model_exclude_none=True)
async def create_graph(request: TextsRequest):
    input_data = jsonable_encoder(request)
Run Code Online (Sandbox Code Playgroud)

n_processes那么这里我该如何排除呢?

fun*_*man 7

由于 Pydantic >= 2.0 不推荐使用 model.dict()model.model_dump(...)来代替。

您可以使用exclude_nonePydantic 的model.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))
Run Code Online (Sandbox Code Playgroud)

输出:

{'data': [{'id': '1', 'text': 'The text 1'}]}
Run Code Online (Sandbox Code Playgroud)

而且,用 writeOptional[int]代替 . 更为惯用Union[int, None]

  • Pydantic >= 2.0 弃用了 `model.dict()`。正如 Eapen Jose 所写,使用“model_dump()”。 (2认同)

Chr*_*ris 5

Pydantic 为使用该方法导出模型提供了以下参数model.dict(...)更新model.dict(...)已弃用(但仍受支持)并替换为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.model_dump(exclude_none=True))
#> {'data': [{'id': '1', 'text': 'The text 1'}]}
print(t.model_dump(exclude_unset=True))
#> {'data': [{'id': '1', 'text': 'The text 1'}], 'n_processes': None}
Run Code Online (Sandbox Code Playgroud)

从响应中排除Unset或参数None

如果您需要从端点的响应中排除Unset或参数,而不必自行调用(或在 Pydantic V2 中)端点内的参数,则可以使用端点的装饰器参数或(请参阅此处此处的相关文档和相关答案)。为了实现这一点,FastAPI 在幕后使用上述(或在 Pydantic V2 中)方法及其or参数。Nonemodel.dict(...)model.model_dump(...)response_model_exclude_unsetresponse_model_exclude_nonemodel.dict(...)model.model_dump(...)exclude_unsetexclude_none

例子:

@app.post("/create", response_model_exclude_unset=True)
async def create_graph(t: TextsRequest):
    return t
Run Code Online (Sandbox Code Playgroud)

或者

@app.post("/create", response_model_exclude_none=True)
async def create_graph(t: TextsRequest):
    return t
Run Code Online (Sandbox Code Playgroud)

关于可选参数

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

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

笔记

q由于默认值,FastAPI 会知道不需要值= None

UnioninUnion[str, None]将允许您的编辑为您提供更好的支持并检测错误。

信息

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

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

因此,无论您选择使用哪个选项,如果后面没有该部分= None,FastAPI 将不知道该参数的值是可选的,因此用户必须为其提供一些值。您还可以通过http://127.0.0.1:8000/docs上自动生成的 API 文档进行检查,其中parameterrequest body将显示为Required字段。

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

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

@app.post("/upload")
def upload(t: Optional[TextsRequest]):
    pass
Run Code Online (Sandbox Code Playgroud)

但是,如果上述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
Run Code Online (Sandbox Code Playgroud)

参数(或主体)是可选的,因为这= None会告诉 FastAPI 该参数不是必需的

在 Python 3.10+ 中

消息是,在 Python 3.10 及更高版本中,您不必担心像Optionaland这样的名称Union,因为您可以简单地使用竖线|(也称为按位或运算符,但该含义与此处无关)来定义可选的参数(或者简单地说,类型的联合)。但是= None,相同的规则也适用于此选项,即,如果您想让参数可选(如下面给出的示例所示),您仍然需要添加该部分。

例子:

@app.post("/upload")
def upload(t: TextsRequest | None = None):
    pass
Run Code Online (Sandbox Code Playgroud)