首页 > 其他分享 >三周精通FastAPI:19 Body - Updates 请求体 - 更新数据

三周精通FastAPI:19 Body - Updates 请求体 - 更新数据

时间:2024-11-03 12:46:20浏览次数:3  
标签:Body None Item 19 FastAPI update item items id

官网文档:https://fastapi.tiangolo.com/zh/tutorial/body-updates/

请求体 - 更新数据

用 PUT 更新数据

更新数据请用 HTTP PUT 操作。把输入数据转换为以 JSON 格式存储的数据(比如,使用 NoSQL 数据库时),可以使用 jsonable_encoder。例如,把 datetime 转换为 str

from typing import List, Union

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

app = FastAPI()


class Item(BaseModel):
    name: Union[str, None] = None
    description: Union[str, None] = None
    price: Union[float, None] = 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 用于接收替换现有数据的数据。

关于更新数据的警告

用 PUT 把数据项 bar 更新为以下内容时:

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

因为上述数据未包含已存储的属性 "tax": 20.2,新的输入模型会把 "tax": 10.5 作为默认值。

因此,本次操作把 tax 的值「更新」为 10.5

用 PATCH 进行部分更新

HTTP PATCH 操作用于更新 部分 数据。

即,只发送要更新的数据,其余数据保持不变。

"笔记"

PATCH 没有 PUT 知名,也怎么不常用。

很多人甚至只用 PUT 实现部分更新。

FastAPI 对此没有任何限制,可以随意互换使用这两种操作。

但本指南也会分别介绍这两种操作各自的用途。

使用 Pydantic 的 exclude_unset 参数

更新部分数据时,可以在 Pydantic 模型的 .dict() 中使用 exclude_unset 参数。

比如,item.dict(exclude_unset=True)

这段代码生成的 dict 只包含创建 item 模型时显式设置的数据,而不包括默认值。然后再用它生成一个只含已设置(在请求中所发送)数据,且省略了默认值的 dict

@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

使用 Pydantic 的 update 参数

接下来,用 .copy() 为已有模型创建调用 update 参数的副本,该参数为包含更新数据的 dict。例如,stored_item_model.copy(update=update_data)

    updated_item = stored_item_model.copy(update=update_data)

更新部分数据小结

简而言之,更新部分数据应:

  • 使用 PATCH 而不是 PUT (可选,也可以用 PUT);
  • 提取存储的数据;
  • 把数据放入 Pydantic 模型;
  • 生成不含输入模型默认值的 dict (使用 exclude_unset 参数);
    • 只更新用户设置过的值,不用模型中的默认值覆盖已存储过的值。
  • 为已存储的模型创建副本,用接收的数据更新其属性 (使用 update 参数)。
  • 把模型副本转换为可存入数据库的形式(比如,使用 jsonable_encoder)。
    • 这种方式与 Pydantic 模型的 .dict() 方法类似,但能确保把值转换为适配 JSON 的数据类型,例如, 把 datetime 转换为 str 。
  • 把数据保存至数据库;
  • 返回更新后的模型。

@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

"提示"

实际上,HTTP PUT 也可以完成相同的操作。 但本节以 PATCH 为例的原因是,该操作就是为了这种用例创建的。

"笔记"

注意,输入模型仍需验证。

因此,如果希望接收的部分更新数据可以省略其他所有属性,则要把模型中所有的属性标记为可选(使用默认值或 None)。

为了区分用于更新所有可选值的模型与用于创建包含必选值的模型,请参照更多模型 一节中的思路。

 

实践

用PATCH进行部分更新。

源代码

将代码写入bodyupdates.py文件

from typing import List, Union

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

app = FastAPI()


class Item(BaseModel):
    name: Union[str, None] = None
    description: Union[str, None] = None
    price: Union[float, None] = 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

启动服务

uvicorn bodyupdates:app --reload

测试

 先用get浏览下:

curl 127.0.0.1:8000/items/bar
{"name":"Bar","description":"The bartenders","price":62.0,"tax":20.2,"tags":[]}

通过PATCH更新字段:

curl -X PATCH "http://127.0.0.1:8000/items/bar" -H "Content-Type: application/json" -d '{"description": "Updated description", "price": 70.0}'

执行更新的输出:

{"name":"Bar","description":"Updated description","price":70.0,"tax":20.2,"tags":[]}

可见确实更改了Bar的price数值。

标签:Body,None,Item,19,FastAPI,update,item,items,id
From: https://blog.csdn.net/skywalk8163/article/details/143298951

相关文章

  • 三周精通FastAPI:20 Dependencies 依赖项 和类作为依赖项
    官方文档:依赖项-FastAPI依赖项¶FastAPI提供了简单易用,但功能强大的依赖注入系统。这个依赖系统设计的简单易用,可以让开发人员轻松地把组件集成至 FastAPI。什么是「依赖注入」¶编程中的「依赖注入」是声明代码(本文中为路径操作函数 )运行所需的,或要使用的「依赖」......
  • SpringBoot图书电子商务网站的设计与实现pr919程序+源码+数据库+调试部署+开发环境
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、研究背景与意义随着网络技术和移动支付的普及,越来越多的读者倾向于通过互联网购买书籍,这为图书电子商务网站的发展提供了广阔的市场空间。然而......
  • Geogebra基础篇019—Geogebra的移动工具(单选、框选、沿点线面体拖动、自由旋转、指定
    注意:关注微信公众号“第五智能”,免费查阅全系列文章(或者微信顶部直接搜索“Geogebra的移动工具”就可以找到了)。关于Geogebra移动工具的知识还是比较繁琐的,比如视图中的对象,大家都知道点击单选,但是怎么框选呢?怎么横移画布、怎么沿点拖动、沿线拖动、沿面拖动、甚至是沿体积......
  • [RoarCTF 2019]Easy Calc
    题目链接:https://buuoj.cn/challenges#[RoarCTF2019]EasyCalc打开环境后如下所示。查看该页面的源代码,发现存在"calc.php"文件,同时,提示设置了WAF。访问"calc.php"文件,发现该页面打印出了PHP源码。即。<?phperror_reporting(0);if(!isset($_GET['num'])){s......
  • [极客大挑战 2019]BuyFlag
    题目链接:https://buuoj.cn/challenges#[极客大挑战2019]BuyFlag打开环境后如下所示。发现右侧中存在一个菜单,并有"PAYFLAG"选项卡,访问其后,响应包如下。HTTP/1.1200OKServer:openrestyDate:Fri,25Oct202415:00:41GMTContent-Type:text/html;charset=UTF-8Con......
  • [ZJCTF 2019]NiZhuanSiWei
    题目链接:https://buuoj.cn/challenges#[ZJCTF2019]NiZhuanSiWei打开环境后如下所示。<?php$text=$_GET["text"];$file=$_GET["file"];$password=$_GET["password"];if(isset($text)&&(file_get_contents($text,'r')===......
  • [极客大挑战 2019]PHP
    题目链接:https://buuoj.cn/challenges#[极客大挑战2019]PHP打开环境后如下所示。题目提示"有一个良好的备份网站的习惯",因此,尝试爆破一下可能的备份文件名(如:backup.zip、www.zip等)。发现该网站的备份文件名为"www.zip",下载后,主要有"index.php"与"class.php"两个源码文......
  • [极客大挑战 2019]BabySQL
    题目链接:https://buuoj.cn/challenges#[极客大挑战2019]BabySQL打开环境后如下所示。尝试以下几种方法的万能密码:不加单引号。加单引号。加双引号。发现加入了单引号后,有SQL错误提示,但是可以发现,题目似乎过滤了用户输入的"or"。接下来,尝试双写绕过。发现可以成......
  • [SUCTF 2019]EasySQL
    题目链接:https://buuoj.cn/challenges#[SUCTF2019]EasySQL打开环境后,如下所示。尝试输入字符:1。尝试输入字符:0后,发现没有输出结果。尝试输入字符串"aaa"、"bbb"等后,发现都跟输入0的结果一致,而输入123、456等非0的内容,都与输入1一致,这里可以猜测(实际上需要比较......
  • [强网杯 2019]随便注
    题目链接:https://buuoj.cn/challenges#[强网杯2019]随便注打开环境后,如下所示。通过输入',确认该处是由单引号闭合。通过输入Payload:'unionselect1;#,可以发现后端对一些关键词进行了过滤。尝试堆叠注入,可以查询到数据库名以及当前使用的数据库中存在的表名。Payload:'%......