FastAPI 教程翻译 - 用户指南 24 - 主体 - 更新

FastAPI 教程翻译 - 用户指南 24 - 主体 - 更新

FastAPI Tutorial - User Guide - Body - updates

Update replacing with PUT

更新为 PUT

To update an item you can use the HTTP PUT operation.

要更新项目,您可以使用 HTTP PUT 操作。

You can use the jsonable_encoder to convert the input data to data that can be stored as JSON (e.g. with a NoSQL database). For example, converting datetime to str.

您可以使用 jsonable_encoder 将输入数据转换为可以存储为 JSON 的数据(例如,使用 NoSQL 数据库)。如,将 datetime 转换为 str

from typing import List

from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str = None
    description: str = None
    price: float = None
    tax: float = 10.5
    tags: List[str] = []


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}


@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: str):
    return items[item_id]


@app.put("/items/{item_id}", response_model=Item)
async def update_item(item_id: str, item: Item):
    update_item_encoded = jsonable_encoder(item)
    items[item_id] = update_item_encoded
    return update_item_encoded

PUT is used to receive data that should replace the existing data.

PUT 用于接收应替换现有数据的数据。

Warning about replacing

有关更换的警告

That means that if you want to update the item bar using PUT with a body containing:

这意味着如果要使用包含以下内容的主体使用 PUT 更新项目 bar

{
    "name": "Barz",
    "price": 3,
    "description": None,
}

because it doesn’t include the already stored attribute "tax": 20.2, the input model would take the default value of "tax": 10.5.

因为它不包含已经存储的属性 "tax": 20.2,所以输入模型将采用 "tax": 10.5

And the data would be saved with that “new” tax of 10.5.

并且数据将以『新的』tax:10.5 保存。

Partial updates with PATCH

PATCH 部分更新

You can also use the HTTP PATCH operation to partially update data.

您还可以使用 HTTP PATCH 操作来部分地更新数据。

This means that you can send only the data that you want to update, leaving the rest intact.

这意味着您只能发送要更新的数据,其余的保持不变。

Note

注意

PATCH is less commonly used and known than PUT.

PATCHPUT 更不常用和已知。

And many teams use only PUT, even for partial updates.

许多团队甚至对部分更新也只使用 PUT

You are free to use them however you want, FastAPI doesn’t impose any restrictions.

您可以随意使用它们,它们都是自由的FastAPI 没有任何限制。

But this guide shows you, more or less, how they are intended to be used.

但是,本指南或多或少地向您展示了如何使用它们。

Using Pydantic’s exclude_unset parameter

使用 Pydantic 的 exclude_unset 参数

If you want to receive partial updates, it’s very useful to use the parameter exclude_unset in Pydantic’s model’s .dict().

如果要接收部分更新,则在 Pydantic 模型的 .dict() 中使用参数 exclude_unset 非常有用。

Like item.dict(exclude_unset=True).

就像 item.dict(exclude_unset=True)

That would generate a dict with only the data that was set when creating the item model, excluding default values.

这将生成仅包含创建 item 模型时设置的数据的 dict,不包括默认值。

Then you can use this to generate a dict with only the data that was set (sent in the request), omitting default values:

然后,您可以使用它生成仅包含设置(在请求中发送)的数据的 dict,而忽略默认值:

from typing import List

from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str = None
    description: str = None
    price: float = None
    tax: float = 10.5
    tags: List[str] = []


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}


@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: str):
    return items[item_id]


@app.patch("/items/{item_id}", response_model=Item)
async def update_item(item_id: str, item: Item):
    stored_item_data = items[item_id]
    stored_item_model = Item(**stored_item_data)
    update_data = item.dict(exclude_unset=True)
    updated_item = stored_item_model.copy(update=update_data)
    items[item_id] = jsonable_encoder(updated_item)
    return updated_item

Using Pydantic’s update parameter

使用 Pydantic 的 update 参数

Now, you can create a copy of the existing model using .copy(), and pass the update parameter with a dict containing the data to update.

现在,您可以使用 .copy() 创建现有模型的副本,并将带有要更新数据的 dictupdate 参数传递给 dict

Like stored_item_model.copy(update=update_data):

就像 stored_item_model.copy(update=update_data)

from typing import List

from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str = None
    description: str = None
    price: float = None
    tax: float = 10.5
    tags: List[str] = []


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}


@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: str):
    return items[item_id]


@app.patch("/items/{item_id}", response_model=Item)
async def update_item(item_id: str, item: Item):
    stored_item_data = items[item_id]
    stored_item_model = Item(**stored_item_data)
    update_data = item.dict(exclude_unset=True)
    updated_item = stored_item_model.copy(update=update_data)
    items[item_id] = jsonable_encoder(updated_item)
    return updated_item

Partial updates recap

部分更新回顾

In summary, to apply partial updates you would:

总之,要应用部分更新,您将:

  • (Optionally) use PATCH instead of PUT.

    (可选)使用 PATCH 而不是 PUT

  • Retrieve the stored data.

    检索存储的数据。

  • Put that data in a Pydantic model.

    将这些数据放到 Pydantic 模型中。

  • Generate a dict without default values from the input model (using exclude_unset).

    从输入模型生成一个没有默认值的 dict(使用 exclude_unset)。

    • This way you can update only the values actually set by the user, instead of overriding values already stored with default values in your model.

      通过这种方式,您只能更新用户实际设置的值,而不是覆盖已经与默认值一起存储在模型的值。

  • Create a copy of the stored model, updating it’s attributes with the received partial updates (using the update parameter).

    创建存储模型的副本,使用接收到的部分更新来更新其属性(使用 update 参数)。

  • Convert the copied model to something that can be stored in your DB (for example, using the jsonable_encoder).

    将复制的模型转换为可以存储在数据库中的模型(例如,使用 jsonable_encoder)。

    • This is comparable to using the model’s .dict() method again, but it makes sure (and converts) the values to data types that can be converted to JSON, for example, datetime to str.

      这类似于再次使用模型的 .dict() 方法,但是它可以确保值(并将其转换为 JSON 的数据类型,例如,将 datetime 转换为 str)。

  • Save the data to your DB.

    将数据保存到数据库。

  • Return the updated model.

    返回更新的模型。

from typing import List

from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str = None
    description: str = None
    price: float = None
    tax: float = 10.5
    tags: List[str] = []


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}


@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: str):
    return items[item_id]


@app.patch("/items/{item_id}", response_model=Item)
async def update_item(item_id: str, item: Item):
    stored_item_data = items[item_id]
    stored_item_model = Item(**stored_item_data)
    update_data = item.dict(exclude_unset=True)
    updated_item = stored_item_model.copy(update=update_data)
    items[item_id] = jsonable_encoder(updated_item)
    return updated_item

Tip

提示

You can actually use this same technique with an HTTP PUT operation.

实际上,您可以对 HTTP PUT 操作使用相同的技术。

But the example here uses PATCH because it was created for these use cases.

但是这里的示例使用 PATCH,因为它是为这些用例创建的。

Note

注意

Notice that the input model is still validated.

请注意,输入模型仍处于验证状态。

So, if you want to receive partial updates that can omit all the attributes, you need to have a model with all the attributes marked as optional (with default values or None).

因此,如果要接收可以忽略所有属性的部分更新,则需要有一个模型,其中所有属性都标记为可选(具有默认值或 None)。

To distinguish from the models with all optional values for updates and models with required values for creation, you can use the ideas described in Extra Models.

要与具有所有可选更新值的模型和具有必需创建值的模型区分开,可以使用 Extra Models 所描述的思想。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值