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 账户的 Free 或 Pro 计划中都包含 GitHub Codespaces 的每月免费使用额度。更多信息,请访问 关于 GitHub Codespaces 的计费。
要为本教程设置 codespace,请导航至此项目的 GitHub 仓库。该 codespace 包含所有必要的配置和依赖项,可让您快速开始 FastAPI 开发。
在本教程中,请选择 dictionarybased 分支。

然后,选择 Code > Codespaces > Create Codespace on <dictionarybased> 分支,为您的项目创建并打开一个 codespace。
完成后,您可以继续阅读下方的替换数据库部分。
在 VS Code 中本地运行
若要成功完成本教程在 VS Code 中的学习,您首先需要设置 Python 开发环境。具体来说,本教程要求:
- Python 3(如果没有安装,请查看安装指南)
- VS Code 的 Python 扩展(有关安装扩展的详细信息,请阅读扩展市场)。
本节中,我们将创建一个文件夹并在 VS Code 中将其作为工作区打开,设置一个 Python 虚拟环境,并安装项目的依赖项。
-
在文件系统中,为本教程创建一个项目文件夹,例如
groceries-plugin。 -
在 VS Code 中打开此新文件夹(File > Open Folder…)。
-
当显示工作区信任 (Workspace Trust) 提示时,选择 Yes, I trust the authors 以允许工作区访问必要的资源和扩展。您可以在文档中了解更多关于工作区信任的信息。
现在,让我们创建一个 requirements.txt 文件,列出我们要为应用程序安装的依赖项。requirements.txt 文件是 Python 开发中的常用做法,用于指定项目依赖的库及其版本。此文件有助于确保任何参与该项目的人都能重现相似的开发环境,是保持一致性的便捷组件。
我们将安装 FastAPI 来创建应用程序,安装 uvicorn 作为服务器,以及 Redis 和 type-redis 用于处理数据存储并与 Redis 数据库交互。
-
在 VS Code 中创建一个新文件(File > New Text File 或 ⌘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 命令)并手动选择该虚拟环境。
开始编码
让我们创建应用程序!
-
通过 File > New File… 创建一个新的 Python 文件,然后选择 Python File。
-
将其保存为
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+Click 终端中的
http://127.0.0.1:8000/URL,在默认浏览器中打开该地址
恭喜!您的 FastAPI 应用已成功运行!
-
通过调试工具栏中的 Stop 按钮,或使用 ⇧F5 (Windows, Linux Shift+F5) 停止调试器。
创建购物清单项的数据模型
现在我们的 FastAPI 应用已经运行,我们可以使用 Pydantic 来定义购物清单项。Pydantic 是一个与 FastAPI 无缝集成的内置数据验证和解析库。它允许您使用带有类型提示的 Python 类来定义数据模型,以便对 API 请求中传入的数据(称为“负载/payloads”)进行自动验证和解析。
让我们为购物清单项创建一个模型。我们将使用 ItemPayload 模型来定义要添加到购物清单中的项的数据结构。该模型将包含三个字段:item_id、item_name 和 quantity。
-
通过 File > New File… 创建一个新的 Python 文件,然后选择 Python File。
-
向文件中添加以下行,并将其保存到
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 之上,后者是一个 Python 静态类型检查器,可以检测代码中的类型错误,从而防止 bug 并提高代码质量。
以下三个步骤是可选的,但考虑到 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 an 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 应用程序中定义的元数据和类型提示动态生成的。 -
在
if quantity <= 0语句旁边设置断点,点击行号左侧的空白区域(或 F9)。调试器将在执行该行之前停止,以便您可以逐行检查代码。
-
启动调试器(F5),然后在浏览器中导航到
http://127.0.0.1:8000/docs。应该会出现一个 Swagger 界面,其中包含应用程序中可用的两个端点:
/items和根路由 (/)。
-
选择
/items路由旁边的向下箭头以展开它,然后点击右侧出现的 Try it out 按钮。
-
通过向
item_name字段传递字符串,向quantity传递数字来添加购物清单项。例如,您可以将item_name设为 apple,将quantity设为 2。 -
选择 Execute。

-
再次打开 VS Code,注意调试器已在你之前设置的断点处停止。

在左侧,所有在该点定义的局部和全局变量都显示在 Run and Debug 视图下的 Variables 窗口中。在我们的示例中,局部变量视图中
item_name设置为 'apple',quantity设置为 2,同时全局变量视图中显示了一个空的grocery_list字典。
现在让我们使用 VS Code 的调试控制台进行一些探索。
-
选择
quantity <= 0语句,右键点击编辑器并选择 Evaluate in Debug Console。
这将打开调试控制台并运行选定的表达式。正如我们示例中所预期的,表达式的求值结果为
False。调试控制台是一个强大的工具,可以快速测试表达式并更好地了解代码在断点时的状态。您还可以使用它来运行任意代码,例如调用函数或打印变量。您可以在 Python 教程中了解更多关于 VS Code Python 调试的信息。
您现在可以通过在调试视图工具栏中选择 Continue,或按 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 容器配置
-
打开命令面板并运行 Dev Containers: Add Dev Container Configuration Files…。
-
选择 Python 3

-
选择默认版本。
-
选择 Redis Server 作为要安装的附加功能,按 OK,然后选择 Keep Defaults。
我们可以选择安装功能 (Features) 以包含在容器中。在本教程中,我们将安装 Redis Server,这是一个由社区贡献的功能,它安装并添加了 Redis 的正确 dev container 设置。

这将在您的工作区中创建一个
.devcontainer文件夹,其中包含一个devcontainer.json文件。让我们对此文件进行一些编辑,以便容器设置中包含安装我们所需的 VS Code 扩展以及项目依赖项的步骤。 -
打开
devcontainer.json文件。 -
在
"features" : { ... }条目后添加一个 ",",这样我们就可以向该文件添加更多设置。接下来,我们将必要的依赖安装命令添加到
devcontainer.json文件的postCreateCommand属性中,以便在容器设置完成后我们的应用程序准备就绪。 -
找到以下内容并从该行中移除注释 (
//),以便在容器创建后可以安装依赖项"postCreateCommand": "pip3 install --user -r requirements.txt",您可以在开发容器规范 (Development Containers Specification) 中了解
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 ] } } -
保存文件。
-
从右下角显示的通知中选择 Reopen in Container,或从命令面板运行 Dev Containers: Reopen in Container 命令。
注意:构建容器可能需要几分钟,具体取决于互联网速度和机器性能。
您可以在 Dev Containers 文档中了解更多关于开发容器配置的信息。
完成后,您将拥有一个功能齐全的、基于 Linux 的工作区,并安装了 Python 3 和 Redis Server。
容器设置完成后,您会在 VS Code 的左下角看到一个指示器。

注意:通过打开扩展视图(⇧⌘X (Windows, Linux Ctrl+Shift+X))并搜索它们,仔细检查 Python 和 Pylance 扩展是否已成功安装在容器中。如果未安装,您可以运行 Install in Dev Container 来安装它们。
所选 Python 解释器的信息可在右下角的状态栏中获得,与 devcontainer.json 文件中指定的版本一致。

注意:如果在状态栏中没找到 Python 解释器信息,您可以点击 Python 解释器指示器(或从命令面板运行 Python: Select Interpreter 命令)并手动选择容器中的 Python 解释器。
我们现在准备进入下一节,我们将在这里替换数据存储。
替换数据库
我们有一个存储购物清单项的字典,但我们想将其替换为 Redis 数据库。在本教程中,我们将使用 Redis 哈希 (hashes) 来存储我们的数据,这是一种可以存储多个键值对的数据结构。
与传统的数据库不同(您可以直接检索项而无需知道其 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 自动添加导入。
现在我们有了一个连接到运行在本地主机 (
host="0.0.0.0") 且监听 6379 端口 (port=6379) 的 Redis 服务器的 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 文件,并选择编辑器右上角的 Run 按钮,或者从命令面板运行 Python: Run Python File in Terminal 命令。
请注意,此操作应谨慎执行,因为它会删除当前数据库中的所有键,如果在生产环境执行,可能会导致数据丢失。
可选:创建 GPT Action
借助 GitHub Codespaces,您可以在使用 GPT Actions 时托管您的应用程序进行测试。GPT Actions 是允许 ChatGPT 与现有 API 交互以增强其能力的工具,从而允许其执行广泛的操作。您可以观看下面的直播录像,学习如何为 ChatGPT 创建自己的购物清单插件。
注意:所有个人 GitHub.com 账户的 Free 或 Pro 计划中都包含 GitHub Codespaces 的每月免费使用额度。更多信息,请访问 关于 GitHub Codespaces 的计费。
后续步骤
感谢您跟随本教程学习!我们希望您在 FastAPI 以及如何在 VS Code 中使用它方面学到了新知识。
本教程的完整代码项目可以在 GitHub 上找到:python-sample-vscode-fastapi-tutorial。
在官方文档中了解更多关于 FastAPI 的信息。
要尝试在生产网站上运行应用程序,请查看教程使用 Docker 容器将 Python 应用程序部署到 Azure App Service。
您也可以查阅这些其它的 VS Code Python 文章