Visual Studio Code 中的 FastAPI 教程
FastAPI 是一个现代的高性能 Web 框架,用于使用 Python 构建 API。它旨在使 API 的构建快速高效,同时提供 API 的自动验证、序列化和文档等功能,使其成为构建 Web 服务和微服务的热门选择。
在本 FastAPI 教程中,我们将使用 FastAPI 创建一个购物清单应用程序。通过本教程,你将了解如何在 Visual Studio Code 终端、编辑器和调试器中使用 FastAPI。本教程不是对 FastAPI 的深入探讨。你可以参考官方 FastAPI 文档。
如果这是你第一次使用 Python,我们建议你从我们的Python 教程开始,熟悉该语言和 VS Code 对 Python 的支持。本教程更适合已经熟悉 Python 并希望学习如何在 VS Code 中使用 FastAPI 的人。
本 FastAPI 教程中已完成的代码项目可在 GitHub 上找到:python-sample-vscode-fastapi-tutorial。
如果你有任何问题,可以在 Python 扩展讨论问答中搜索答案或提问。
设置项目
有多种方法可以为本教程设置项目。我们将介绍如何在GitHub Codespaces和本地 VS Code 中设置它。
GitHub Codespaces
你可以将此项目设置为在GitHub Codespaces中进行开发,你可以在其中远程编写、调试和运行应用程序。Codespace 提供了一个在云中托管的完全配置的开发环境,无需进行本地设置。此环境包括项目的依赖项、工具和扩展,确保一致且可重现的开发体验。它通过提供实时编辑、集成版本控制以及对调试和测试工具的轻松访问来简化协作,同时保持项目的安全性和可靠性。
注意:所有 GitHub.com 账户都包含在免费或专业计划中,每月有免费使用 GitHub Codespaces 的配额。有关详细信息,请参阅关于 GitHub Codespaces 的计费。
要为本教程设置 codespace,请导航到此项目的 GitHub 存储库。此 codespace 包含所有必要的配置和依赖项,可以快速开始 FastAPI 开发。
对于本教程,选择 dictionarybased 分支
然后,选择 Code > Codespaces > Create Codespace on
完成后,你可以继续下面的替换数据库部分。
在本地 VS Code 中
要在 VS Code 中成功完成本教程,你首先需要设置 Python 开发环境。具体来说,本教程需要
- Python 3(如果尚未安装,请查看安装指南)
- VS Code 的 Python 扩展(有关安装扩展的更多详细信息,你可以阅读扩展市场)。
在本节中,我们将创建一个文件夹作为 VS Code 中的工作区打开,设置一个 Python 虚拟环境,并安装项目的依赖项。
-
在文件系统中,为本教程创建一个项目文件夹,例如
groceries-plugin
。 -
在 VS Code 中打开此新文件夹 (文件 > 打开文件夹…)。
-
当工作区信任提示出现时,选择 是,我信任作者,以允许工作区访问必要的资源和扩展。你可以在文档中了解更多关于工作区信任的信息。
现在,让我们创建一个 requirements.txt
文件,其中列出了我们希望为应用程序安装的依赖项。requirements.txt
文件是 Python 开发中的常见做法,用于指定项目所依赖的库及其版本。此文件有助于确保从事项目工作的任何人都可以重新创建类似的开发环境,使其成为保持一致性的便捷组件。
我们将安装 FastAPI 用于创建应用程序,uvicorn 作为服务器,以及 Redis 和 type-redis
用于处理数据存储和与 Redis 数据库交互。
-
在 VS Code 中创建一个新文件 (文件 > 新建文本文件 或 ⌘N (Windows, Linux Ctrl+N))。
-
向其中添加以下内容
fastapi redis types-redis uvicorn
-
保存文件 (⌘S (Windows, Linux Ctrl+S)) 并将其命名为
requirements.txt
。 -
通过打开命令面板 (⇧⌘P (Windows, Linux Ctrl+Shift+P)) 并运行 Python: Create Environment 命令来创建虚拟环境。
注意:此步骤可能需要几分钟才能完成。
-
当询问环境类型时,选择 Venv
-
然后选择机器上可用的最新版 Python
-
从下拉列表中选择
requirements.txt
文件,以便自动安装依赖项,然后选择 OK
将创建虚拟环境,自动安装依赖项,并为工作区选择该环境供 Python 扩展使用。你可以通过检查 VS Code 的右下角来确认它已选择
注意:如果你在状态栏中找不到新创建的环境信息,你可以点击 Python 解释器指示器(或从命令面板运行 Python: Select Interpreter 命令)并手动选择虚拟环境。
开始编码
让我们来创建应用程序!
-
使用 文件 > 新建文件… 创建一个新的 Python 文件,然后选择 Python 文件。
-
将其保存为
main.py
(⇧⌘S (Windows, Linux Ctrl+Shift+S)) 在groceries-plugin
文件夹中。 -
将以下代码添加到
main.py
并保存文件from fastapi import FastAPI app = FastAPI() @app.get("/") def root(): return {"message": "Hello World"}
-
通过启动调试器 (F5) 来运行代码。
-
从下拉菜单中,从列表中选择 FastAPI 配置选项
这将自动创建一个调试配置,通过调试器调用 uvicorn 启动应用程序服务器,并允许你逐行检查源代码以检查其行为。你应该在终端中看到如下内容
提示:如果你的默认端口已被占用,请停止调试器并打开命令面板 (⇧⌘P (Windows, Linux Ctrl+Shift+P)),搜索 Debug: Add Configuration,选择 Python Debugger,然后选择 FastAPI。这将创建一个自定义配置文件
.vscode/launch.json
,你可以对其进行编辑。在"args":[]
中添加以下内容以设置自定义端口:"--port=5000"
。保存文件,然后使用 (F5) 重新启动调试器。 -
Ctrl+单击 终端中的
http://127.0.0.1:8000/
URL,以在你默认的浏览器中打开该地址恭喜!你的 FastAPI 应用程序已启动并正在运行!
-
通过调试工具栏中的 停止 按钮或通过 ⇧F5 (Windows, Linux Shift+F5) 停止调试器。
创建购物清单项目的模型
现在我们已经启动了 FastAPI 应用程序,我们可以使用 Pydantic 来定义我们的购物清单项目,Pydantic 是一个数据验证和解析库,可以与 FastAPI 无缝集成。Pydantic 允许你使用带有类型提示的 Python 类来定义数据模型,以自动验证和解析 API 请求中传入的数据(称为“负载”)。
让我们为购物清单项目创建一个模型。我们将使用 ItemPayload
模型来定义要添加到购物清单中的项目的数据结构。此模型将包含三个字段:item_id
、item_name
和 quantity
。
-
使用 文件 > 新建文件… 创建一个新的 Python 文件,然后选择 Python 文件。
-
将以下行添加到文件中,然后将其保存到
groceries-plugin
文件夹中,文件名为models.py
(⇧⌘S (Windows, Linux Ctrl+Shift+S))from typing import Optional from pydantic import BaseModel class ItemPayload(BaseModel): item_id: Optional[int] item_name: str quantity: int
Pylance 是 VS Code 中 Python 的默认语言服务器,它支持类型提示功能,这对于使用 Pydantic 模型和 FastAPI 非常有帮助。这是因为 Pylance 构建在 Pyright 之上,Pyright 是 Python 的静态类型检查器,可以检测代码中的类型错误,从而防止错误并提高代码质量。
以下三个步骤是可选的,但鉴于 FastAPI 广泛使用类型提示来提高代码可读性和验证,我们可以利用 Pylance 的类型检查功能来尽早发现错误
-
打开“设置”编辑器 (⌘, (Windows, Linux Ctrl+,))。
-
搜索“python type checking mode”并将其设置为
basic
以进行基本类型检查。Pylance 现在将显示诊断和警告以捕获简单的类型相关错误。或者,你可以将其设置为strict
以强制执行更高级的类型检查规则。 -
接下来,搜索“Python inlay type hints”,并为 Variable Types 和 Function Return Types 启用内联提示
创建路由
现在我们需要一个地方来存储购物清单项目。为简单起见,让我们从一个空字典开始。
-
首先,让我们导入样本所需的所有包。打开
main.py
文件并将第一行导入替换为以下行from fastapi import FastAPI, HTTPException from models import ItemPayload
-
现在在
app = FastAPI()
下面添加以下行grocery_list: dict[int, ItemPayload] = {}
这将创建一个新的空字典,它接收
int
类型的键(作为项目 ID)和ItemPayload
类型的值。现在我们将在 FastAPI 应用程序中定义路由。在 Web 应用程序的上下文中,路由就像将特定 URL 映射到处理它们的代码的路径。这些路由充当应用程序中不同功能的入口点。当客户端(例如 Web 浏览器或另一个程序)向我们的应用程序发送带有特定 URL 的请求时,FastAPI 会根据 URL 将该请求路由到相应的函数(也称为路由处理程序或视图函数),该函数处理请求并生成响应。
让我们继续定义路由,以添加和检索单个项目,以及返回购物清单中的所有项目。
-
在
main.py
文件末尾添加以下路由# Route to add a item @app.post("/items/{item_name}/{quantity}") def add_item(item_name: str, quantity: int): if quantity <= 0: raise HTTPException(status_code=400, detail="Quantity must be greater than 0.") # if item already exists, we'll just add the quantity. # get all item names items_ids = {item.item_name: item.item_id if item.item_id is not None else 0 for item in grocery_list.values()} if item_name in items_ids.keys(): # get index of item_name in item_ids, which is the item_id item_id = items_ids[item_name] grocery_list[item_id].quantity += quantity # otherwise, create a new item else: # generate an ID for the item based on the highest ID in the grocery_list item_id = max(grocery_list.keys()) + 1 if grocery_list else 0 grocery_list[item_id] = ItemPayload( item_id=item_id, item_name=item_name, quantity=quantity ) return {"item": grocery_list[item_id]}
如果你在上一节中启用了类型提示,你可能会注意到 Pylance 添加了函数返回类型以及
item_ids
和item_id
类型的内联提示。你可以选择双击每个建议以将其插入到代码中现在让我们检查此路由是否按预期工作。最快的方法是同时使用 VS Code 的调试器和 FastAPI 的
/docs
端点,后者提供有关所有可用 API 路由的信息,并允许你与 API 交互以探索其参数和响应。此文档是根据 FastAPI 应用程序中定义的元数据和类型提示动态生成的。 -
通过单击行号的左侧边距(或 F9),在
if quantity <= 0
语句旁边添加一个断点。调试器将在该行执行之前停止,以便你可以逐行检查代码。 -
启动调试器 (F5),然后在浏览器中导航到
http://127.0.0.1:8000/docs
。应该有一个 Swagger 界面,其中包含应用程序中可用的两个端点:
/items
和根 (/
)。 -
选择
/items
路由旁边的向下箭头以展开它,然后选择右侧出现的 试用 按钮。 -
通过将字符串传递给
item_name
字段并将数字传递给quantity
来添加一个购物清单项目。例如,你可以将 apple 作为item_name
,将 2 作为quantity
。 -
选择 执行。
-
再次打开 VS Code,注意调试器已在你之前设置的断点处停止。
在左侧,“运行和调试”视图下的“变量”窗口中显示了此时定义的所有局部变量和全局变量。在我们的示例中,
item_name
在局部变量视图下设置为“apple”,quantity
设置为 2,并且在全局变量视图下有一个空的grocery_list
字典。现在让我们使用 VS Code 的调试控制台进行一些探索。
-
选择
quantity <= 0
语句,右键单击编辑器并选择 在调试控制台中评估这将打开调试控制台并运行所选表达式。如我们的示例中预期,该表达式评估为
False
。调试控制台是一个强大的工具,可以快速测试表达式并更好地了解断点处代码的状态。你还可以使用它来运行任意代码,例如调用函数或打印变量。你可以在Python 教程中了解更多关于 VS Code 中的 Python 调试。
现在你可以通过选择调试视图工具栏中的 继续,或按 F5 来继续执行代码。
最后,让我们为应用程序添加剩余的路由,以便我们可以列出所有项目或特定项目,以及将它们从我们的购物清单中删除。你可以让调试器保持运行状态,因为它会在你下一步保存更改时自动重新加载应用程序。
-
将
main.py
中的内容替换为以下代码from fastapi import FastAPI, HTTPException from models import ItemPayload app = FastAPI() grocery_list: dict[int, ItemPayload] = {} # Route to add an item @app.post("/items/{item_name}/{quantity}") def add_item(item_name: str, quantity: int) -> dict[str, ItemPayload]: if quantity <= 0: raise HTTPException(status_code=400, detail="Quantity must be greater than 0.") # if item already exists, we'll just add the quantity. # get all item names items_ids: dict[str, int] = { item.item_name: item.item_id if item.item_id is not None else 0 for item in grocery_list.values() } if item_name in items_ids.keys(): # get index of item_name in item_ids, which is the item_id item_id: int = items_ids[item_name] grocery_list[item_id].quantity += quantity # otherwise, create a new item else: # generate an ID for the item based on the highest ID in the grocery_list item_id: int = max(grocery_list.keys()) + 1 if grocery_list else 0 grocery_list[item_id] = ItemPayload( item_id=item_id, item_name=item_name, quantity=quantity ) return {"item": grocery_list[item_id]} # Route to list a specific item by ID @app.get("/items/{item_id}") def list_item(item_id: int) -> dict[str, ItemPayload]: if item_id not in grocery_list: raise HTTPException(status_code=404, detail="Item not found.") return {"item": grocery_list[item_id]} # Route to list all items @app.get("/items") def list_items() -> dict[str, dict[int, ItemPayload]]: return {"items": grocery_list} # Route to delete a specific item by ID @app.delete("/items/{item_id}") def delete_item(item_id: int) -> dict[str, str]: if item_id not in grocery_list: raise HTTPException(status_code=404, detail="Item not found.") del grocery_list[item_id] return {"result": "Item deleted."} # Route to remove some quantity of a specific item by ID @app.delete("/items/{item_id}/{quantity}") def remove_quantity(item_id: int, quantity: int) -> dict[str, str]: if item_id not in grocery_list: raise HTTPException(status_code=404, detail="Item not found.") # if quantity to be removed is higher or equal to item's quantity, delete the item if grocery_list[item_id].quantity <= quantity: del grocery_list[item_id] return {"result": "Item deleted."} else: grocery_list[item_id].quantity -= quantity return {"result": f"{quantity} items removed."}
-
保存文件 (⌘S (Windows, Linux Ctrl+S))。应用程序应该会自动重新加载。
你现在可以再次打开 /docs
页面并测试新路由,使用调试器和调试控制台更好地理解代码执行。完成后,你可以停止调试器 (⇧F5 (Windows, Linux Shift+F5))。你还可以通过点击我们步骤 4 中添加的断点来将其删除。
恭喜!你现在拥有一个功能齐全的 FastAPI 应用程序,其中包含添加、列出和删除购物清单项目的路由。
设置数据存储
此时,你已经拥有了一个具有基本功能的应用程序工作版本。本节将指导你设置数据存储以实现持久化,但如果你对已经学到的内容感到满意,则可以选择跳过此部分。
到目前为止,我们正在将数据存储在字典中,这不是理想的,因为应用程序重新启动时所有数据都会丢失。
为了持久化数据,我们将使用 Redis,它是一个开源的内存数据结构存储。由于其速度和多功能性,Redis 通常用作各种应用程序中的数据存储系统,包括 Web 应用程序、实时分析系统、缓存层、本教程等等。
如果您已经在使用我们现有模板的 GitHub Codespaces,则可以直接跳到替换数据库部分。
如果你在 Windows 上,可以通过设置 Docker 容器或 GitHub Codespace 来使用 Redis。在本教程中,我们将使用 Docker 容器,但你可以参考上文中关于如何设置 GitHub Codespace 的说明。
否则,如果你在 Linux 或 macOS 机器上,可以通过遵循其网站上的说明安装 Redis,然后跳到替换数据库部分。
在 Windows 上设置 Docker 容器
VS Code Dev Containers 扩展提供了一种简化方法,可以将你的项目、其依赖项和所有必要的工具整合到一个整洁的容器中,从而创建一个功能齐全的开发环境。该扩展允许你在 VS Code 中打开容器内部(或挂载到容器中)的项目,你将在其中拥有其完整的特性集。
对于以下步骤,请确保你的机器上已安装以下要求
要求
创建开发容器配置
-
打开命令面板并运行 Dev Containers: Add Dev Container Configuration Files…。
-
选择 Python 3
-
选择默认版本。
-
选择 Redis Server 作为要安装的附加功能,按 OK,然后选择 Keep Defaults。
我们可以选择安装要包含在容器中的功能。对于本教程,我们将安装 Redis Server,这是一个社区贡献的功能,用于安装 Redis 并添加适当的开发容器设置。
这将在你的工作区中创建一个
.devcontainer
文件夹,其中包含一个devcontainer.json
文件。让我们对该文件进行一些编辑,以便容器设置包含安装我们需要的 VS Code 扩展以及项目依赖项等步骤。 -
打开
devcontainer.json
文件。 -
在
"features" : { ... }
条目后添加一个“,”,以便我们可以向文件中添加更多设置。接下来,我们将在
devcontainer.json
文件中向postCreateCommand
属性添加必要的依赖项安装命令,以便一旦容器设置完成,我们的应用程序就可以运行。 -
找到以下内容并删除该行中的注释 (
//
),以便在创建容器后可以安装依赖项"postCreateCommand": "pip3 install --user -r requirements.txt",
你可以在开发容器规范中了解有关
postCreateCommand
和更多生命周期脚本的信息。现在我们将使用
customizations
属性添加我们希望安装在容器中的 VS Code 扩展。 -
将以下设置添加到
devcontainer.json
// Use 'postCreateCommand' to run commands after the container is created. "postCreateCommand": "pip3 install --user -r requirements.txt", // Configure tool-specific properties. "customizations": { "vscode": { "extensions": [ "ms-python.python", //Python extension ID "ms-python.vscode-pylance" //Pylance extension ID ] } }
-
保存文件。
-
从右下角显示的通知中选择 在容器中重新打开,或从命令面板运行 Dev Containers: Reopen in Container 命令。
注意:构建容器可能需要几分钟,具体取决于互联网速度和机器性能。
你可以在开发容器文档中了解有关开发容器配置的更多信息。
完成后,你将拥有一个完全配置的基于 Linux 的工作区,其中安装了 Python 3 和 Redis 服务器。
容器设置完成后,你会在 VS Code 的左下角看到一个指示器
注意:双重检查 Python 和 Pylance 扩展是否已成功安装在容器中,方法是打开“扩展”视图 (⇧⌘X (Windows, Linux Ctrl+Shift+X)) 并搜索它们。如果没有,你可以通过运行 Install in Dev Container 来安装它们。
选定的 Python 解释器信息在右下角的状态栏中可用,与 devcontainer.json
文件中指定的版本匹配
注意:如果你在状态栏中找不到 Python 解释器信息,可以点击 Python 解释器指示器(或从命令面板运行 Python: Select Interpreter 命令)并手动选择容器中的 Python 解释器。
我们现在准备进入下一节,我们将替换数据存储。
替换数据库
我们有一个存储购物清单项目的字典,但我们想用 Redis 数据库替换它。在本教程中,我们将使用 Redis 哈希来存储我们的数据,它是一种可以存储多个键值对的数据结构。
与传统数据库不同,你可以在不知道其 ID 的情况下检索项目,你需要知道 Redis 哈希键才能从中检索值。在本教程中,我们将创建一个名为 item_name_to_id
的哈希以按名称检索项目,并将它们映射到其 ID。此外,我们还将创建其他哈希以按 ID 检索项目,将它们映射到其名称和数量。每个项目哈希都命名为 item_id:{item_id}
,并具有两个字段:item_name
和 quantity
。
首先,让我们用连接到 Redis 服务器的 Redis 客户端对象替换字典。
-
在
main.py
文件中,将文件开头的grocery_list: dict[int, ItemPayload] = {}
替换为以下行redis_client = redis.StrictRedis(host='0.0.0.0', port=6379, db=0, decode_responses=True)
Pylance 将显示一条错误消息,因为 Redis 尚未导入。
-
将光标放在编辑器中的“redis”上,然后单击显示的小灯泡(或 ⌘. (Windows, Linux Ctrl+.))。然后选择 Add 'import redis'。
提示:你可以通过在“设置”编辑器 (⌘, (Windows, Linux Ctrl+,)) 中查找 Auto Import Completions 设置并启用它来设置 Pylance 自动添加导入。
我们现在有一个 Redis 客户端对象,它连接到在本地主机 (
host="0.0.0.0"
) 上运行并在端口 6379 (port=6379
) 上侦听的 Redis 服务器。db
参数指定要使用的 Redis 数据库。Redis 支持多个数据库,在此代码中我们将使用数据库 0,它是默认数据库。我们还传递decode_responses=True
以便将响应解码为字符串(而不是字节)。让我们在第一个路由
add_item
中进行更多替换。我们可以直接从 Redis 哈希中获取该信息,而不是查看字典中的所有键来查找已提供的项目名称。我们假设
item_name_to_id
哈希已经存在,将项目名称映射到其 ID(别担心,我们很快就会添加此代码!)。然后,我们可以通过调用 Redis 的hget
方法来获取请求中收到的项目名称的 ID,如果请求的名称已存在于哈希中,它将返回项目 ID,否则返回None
。 -
删除包含以下内容的代码行
items_ids = {item.item_name: item.item_id if item.item_id is not None else 0 for item in grocery_list.values()}
并将其替换为
item_id = redis_client.hget("item_name_to_id", item_name)
请注意,Pylance 对此更改提出了问题。这是因为
hget
方法返回str
或None
(如果项目不存在)。但是,我们尚未替换的代码行期望item_id
的类型为int
。让我们通过重命名item_id
符号来解决此警告。 -
将
item_id
重命名为item_id_str
。 -
如果你启用了内联提示,Pylance 应该会在
item_id_str
旁边显示变量类型提示。你可以选择双击以接受它 -
如果项目不存在,则
item_id_str
为None
。所以现在我们可以删除包含以下内容的代码行if item_name in items_ids.keys():
并将其替换为
if item_id_str is not None:
现在我们已经将项目 ID 作为字符串,我们需要将其转换为
int
并更新项目的数量。目前,我们的 Redis 哈希只将项目名称映射到其 ID。为了也映射项目 ID 到它们的名称和数量,我们将为每个项目创建一个单独的 Redis 哈希,使用"item_id:{item_id}"
作为我们的哈希名称,以便更容易按 ID 检索。我们还将为这些哈希中的每一个添加item_name
和quantity
字段。 -
删除
if
块中的代码item_id: int = items_ids[item_name] grocery_list[item_id].quantity += quantity
并添加以下内容,将
item_id
转换为int
,然后通过调用 Redis 的hincrby
方法来增加项目的数量。此方法将"quantity"
字段的值增加请求中给定的数量 (quantity
)item_id = int(item_id_str) redis_client.hincrby(f"item_id:{item_id}", "quantity", quantity)
我们现在只需要替换当项目不存在(即
item_id_str
为None
)时的代码。在这种情况下,我们将生成一个新的item_id
,为该项目创建一个新的 Redis 哈希,然后添加提供的项目名称和数量。为了生成新的
item_id
,让我们使用 Redis 的incr
方法,传递一个新的哈希名为"item_ids"
。此哈希用于存储最后生成的 ID,因此我们每次创建新项目时都可以增加它,确保它们都具有唯一的 ID。 -
删除包含以下内容的代码行
item_id: int = max(grocery_list.keys()) + 1 if grocery_list else 0
并添加以下内容
item_id: int = redis_client.incr("item_ids")
当此
incr
调用首次以item_ids
键运行时,Redis 会创建该键并将其映射到值1
。然后,每次后续运行时,它会将存储的值增加 1。现在我们将使用
hset
方法将项目添加到 Redis 哈希中,并为字段(item_id
、item_name
和quantity
)和值(项目新创建的 ID 及其提供的名称和数量)提供映射。 -
删除包含以下内容的代码行
grocery_list[item_id] = ItemPayload( item_id=item_id, item_name=item_name, quantity=quantity )
并将其替换为以下内容
redis_client.hset( f"item_id:{item_id}", mapping={ "item_id": item_id, "item_name": item_name, "quantity": quantity, })
现在我们只需要通过设置我们在开头引用的哈希
item_name_to_id
,将新创建的 ID 映射到项目名称。 -
将此行添加到路由末尾的
else
块中redis_client.hset("item_name_to_id", item_name, item_id)
-
删除包含以下内容的代码行
return {"item": grocery_list[item_id]}
并将其替换为
return {"item": ItemPayload(item_id=item_id, item_name=item_name, quantity=quantity)}
-
如果你愿意,可以尝试对其他路由进行类似的替换。否则,你可以将文件的全部内容替换为以下代码
import redis from fastapi import FastAPI, HTTPException from models import ItemPayload app = FastAPI() redis_client = redis.StrictRedis(host="0.0.0.0", port=6379, db=0, decode_responses=True) # Route to add an item @app.post("/items/{item_name}/{quantity}") def add_item(item_name: str, quantity: int) -> dict[str, ItemPayload]: if quantity <= 0: raise HTTPException(status_code=400, detail="Quantity must be greater than 0.") # Check if item already exists item_id_str: str | None = redis_client.hget("item_name_to_id", item_name) if item_id_str is not None: item_id = int(item_id_str) redis_client.hincrby(f"item_id:{item_id}", "quantity", quantity) else: # Generate an ID for the item item_id: int = redis_client.incr("item_ids") redis_client.hset( f"item_id:{item_id}", mapping={ "item_id": item_id, "item_name": item_name, "quantity": quantity, }, ) # Create a set so we can search by name too redis_client.hset("item_name_to_id", item_name, item_id) return { "item": ItemPayload(item_id=item_id, item_name=item_name, quantity=quantity) } # Route to list a specific item by ID but using Redis @app.get("/items/{item_id}") def list_item(item_id: int) -> dict[str, dict[str, str]]: if not redis_client.hexists(f"item_id:{item_id}", "item_id"): raise HTTPException(status_code=404, detail="Item not found.") else: return {"item": redis_client.hgetall(f"item_id:{item_id}")} @app.get("/items") def list_items() -> dict[str, list[ItemPayload]]: items: list[ItemPayload] = [] stored_items: dict[str, str] = redis_client.hgetall("item_name_to_id") for name, id_str in stored_items.items(): item_id: int = int(id_str) item_name_str: str | None = redis_client.hget(f"item_id:{item_id}", "item_name") if item_name_str is not None: item_name: str = item_name_str else: continue # skip this item if it has no name item_quantity_str: str | None = redis_client.hget( f"item_id:{item_id}", "quantity" ) if item_quantity_str is not None: item_quantity: int = int(item_quantity_str) else: item_quantity = 0 items.append( ItemPayload(item_id=item_id, item_name=item_name, quantity=item_quantity) ) return {"items": items} # Route to delete a specific item by ID but using Redis @app.delete("/items/{item_id}") def delete_item(item_id: int) -> dict[str, str]: if not redis_client.hexists(f"item_id:{item_id}", "item_id"): raise HTTPException(status_code=404, detail="Item not found.") else: item_name: str | None = redis_client.hget(f"item_id:{item_id}", "item_name") redis_client.hdel("item_name_to_id", f"{item_name}") redis_client.delete(f"item_id:{item_id}") return {"result": "Item deleted."} # Route to remove some quantity of a specific item by ID but using Redis @app.delete("/items/{item_id}/{quantity}") def remove_quantity(item_id: int, quantity: int) -> dict[str, str]: if not redis_client.hexists(f"item_id:{item_id}", "item_id"): raise HTTPException(status_code=404, detail="Item not found.") item_quantity: str | None = redis_client.hget(f"item_id:{item_id}", "quantity") # if quantity to be removed is higher or equal to item's quantity, delete the item if item_quantity is None: existing_quantity: int = 0 else: existing_quantity: int = int(item_quantity) if existing_quantity <= quantity: item_name: str | None = redis_client.hget(f"item_id:{item_id}", "item_name") redis_client.hdel("item_name_to_id", f"{item_name}") redis_client.delete(f"item_id:{item_id}") return {"result": "Item deleted."} else: redis_client.hincrby(f"item_id:{item_id}", "quantity", -quantity) return {"result": f"{quantity} items removed."}
-
通过与
/docs
路由交互,重新运行调试器以测试此应用程序。完成后,你可以停止调试器。
恭喜!你现在拥有一个功能齐全的 FastAPI 应用程序,其中包含添加、列出和删除购物清单项目的路由,并且数据持久化在 Redis 数据库中。
可选:设置数据库删除
现在数据已由 Redis 持久化,你可能希望创建一个脚本来清除所有测试数据。为此,创建一个名为 flushdb.py
的新文件,其内容如下
import redis
redis_client = redis.StrictRedis(host='0.0.0.0', port=6379, db=0, decode_responses=True)
redis_client.flushdb()
然后,当你想要重置数据库时,可以在 VS Code 中打开 flushdb.py
文件并选择编辑器右上角的 运行 按钮,或者从命令面板运行 Python: 在终端中运行 Python 文件 命令。
请注意,这应谨慎操作,因为它将删除当前数据库中的所有键,如果在生产环境中操作,可能会导致数据丢失。
可选:创建一个 ChatGPT 插件
使用 GitHub Codespaces,你可以在使用 ChatGPT 插件时托管你的应用程序进行测试。ChatGPT 插件是使 ChatGPT 能够与现有 API 交互以增强 ChatGPT 能力的工具,使其能够执行各种操作。ChatGPT 插件目前尚未公开发布,但你可以加入他们的等待列表以获取访问权限。一旦你获得访问权限,你可以按照下面的直播录像创建你自己的 ChatGPT 购物清单插件
注意:所有 GitHub.com 个人账户都包含在免费或专业计划中,每月有免费使用 GitHub Codespaces 的配额。有关详细信息,请参阅关于 GitHub Codespaces 的计费。
后续步骤
感谢你跟随本教程!我们希望你学到了关于 FastAPI 以及如何在 VS Code 中使用它的一些新知识。
本教程中已完成的代码项目可在 GitHub 上找到:python-sample-vscode-fastapi-tutorial。
在官方文档中了解更多关于 FastAPI 的信息。
要在生产网站上试用该应用程序,请查看教程使用 Docker 容器将 Python 应用程序部署到 Azure App Service。
你还可以查阅这些其他 VS Code Python 文章