使用 fastapi 更新具有可为空属性的对象的最佳方法

Best way to update objects with nullable properties with fastapi

我正在构建一个简单的 REST API。 如果要更新的对象包含可以包含null的属性,那么在fastapi中定义它的最佳方式是什么?

使用pydantic.BaseModel时,不支持不更新属性的用法

示例:

from fastapi import Body, FastAPI
from typing import Optional, Literal
import dataclasses

app = FastAPI()

@dataclasses.dataclass
class User:
    name: str
    type: Optional[Literal['admin', 'guest']]

user = User('test_user', 'admin')

class UpdateUser(BaseModel):
    name: str
    type: Optional[Literal['admin', 'guest']]

@app.put('/')
def put(update_user: UpdateUser):
    # In the case of BaseModel, I don't know the difference between the property 
    # that I don't update and the property that I want to update with None,
    # so I always update with None.
    user.name = update_user.name
    user.type = update_user.type

我认为最简单的方法是使用dict

示例:

from fastapi import Body, FastAPI
from typing import Optional, Literal
import dataclasses

app = FastAPI()

@dataclasses.dataclass
class User:
    id: int
    name: str
    type: Optional[Literal['admin', 'guest']]

user = User(1, 'test_user', 'admin')

@app.put('/')
def put(body = Body(...)):
    if 'name' in body:
        user.name = body.name
    if 'type' in body:
        user.type = body.type

但是,在这种情况下,无法像 BaseModel 那样指定用于请求的 JSON 类型。

如何在保留类型信息的同时实现具有类似 dict 灵活性的更新过程?

原来这是一个典型的补丁请求。 在更新的时候,UpdateUser可以接收到,update_user.dict(exclude_unset=True)可以接收到一个只包含需要更新的部分的字典。

示例:

from fastapi import Body, FastAPI
from typing import Optional, Literal
import dataclasses

app = FastAPI()

@dataclasses.dataclass
class User:
    name: str
    type: Optional[Literal['admin', 'guest']]

user = User('test_user', 'admin')

class UpdateUser(BaseModel):
    name: str
    type: Optional[Literal['admin', 'guest']]

@app.patch('/')
def patch(update_user: UpdateUser):
    update_user_dict = update_user.dict(exclude_unset=True)

    if 'name' in update_user_dict:
        user.name = update_user.name
    if 'type' in update_user_dict:
        user.type = update_user.type

https://fastapi.tiangolo.com/tutorial/body-updates/#using-pydantics-exclude_unset-parameter