Visual Studio Code 中的 FastAPI 教程
FastAPI 是一個現代高效能的 Python Web 框架,用於構建 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 中遠端編寫程式碼、除錯和執行應用程式。codespace 提供了一個完全配置的雲託管開發環境,無需本地設定。此環境包括您專案的依賴項、工具和擴充套件,確保一致且可重現的開發體驗。它透過提供即時編輯、整合版本控制以及輕鬆訪問除錯和測試工具來簡化協作,同時保持專案的安全性和可靠性。
注意:所有 GitHub.com 帳戶都包含在免費或專業計劃中的 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 中開啟此新資料夾 (檔案 > 開啟資料夾…)。
-
當出現工作區信任提示時,選擇是,我信任作者以允許工作區訪問必要的資源和擴充套件。您可以在文件中瞭解有關工作區信任的更多資訊。
現在,讓我們建立一個 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+Click 終端中的
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 的靜態型別檢查器,可以檢測程式碼中的型別錯誤,以防止 bug 並提高程式碼質量。
以下三個步驟是可選的,但考慮到 FastAPI 廣泛使用型別提示來提高程式碼可讀性和驗證,我們可以利用 Pylance 的型別檢查功能來儘早發現錯誤
-
開啟設定編輯器(⌘, (Windows, Linux Ctrl+,))。
-
搜尋“python type checking mode”並將其設定為
basic
進行基本型別檢查。Pylance 現在將顯示診斷和警告以捕獲簡單的型別相關錯誤。或者,您可以將其設定為strict
以強制執行更高階的 型別檢查規則。 -
接下來,搜尋“Python inlay type hints”,併為變數型別和函式返回型別啟用內聯提示
建立路由
現在我們需要一個地方來儲存購物清單項。為了簡單起見,讓我們從一個空字典開始。
-
首先,讓我們匯入示例所需的所有包。開啟
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
路由旁邊的向下箭頭以展開它,然後選擇右側出現的 Try it out 按鈕。 -
透過向
item_name
欄位傳遞字串並向quantity
傳遞數字來新增購物清單項。例如,您可以提供 apple 作為item_name
,2 作為quantity
。 -
選擇 Execute。
-
再次開啟 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 開發容器 擴充套件提供了一種簡化方法,可以將您的專案、其依賴項和所有必要的工具整合到一個整潔的容器中,從而建立一個功能齊全的開發環境。該擴充套件允許您在 VS Code 中在容器內部(或掛載到容器中)開啟您的專案,您將在其中擁有其完整的功能集。
對於以下步驟,請確保您的機器上安裝了以下要求
要求
- 適用於 Windows 的 Docker
- 開發容器 擴充套件
建立開發容器配置
-
開啟命令面板並執行 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 Server。
容器設定完成後,您會在 VS Code 的左下角看到一個指示器
注意:透過開啟擴充套件檢視(⇧⌘X (Windows, Linux Ctrl+Shift+X))並搜尋它們,仔細檢查 Python 和 Pylance 擴充套件是否已成功安裝在容器中。如果沒有,您可以透過執行 在開發容器中安裝 來安裝它們。
所選 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+.))。然後選擇 新增 'import redis'。
提示:您可以透過在設定編輯器(⌘, (Windows, Linux Ctrl+,))中查詢 自動匯入補全 設定並啟用它來設定 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")
當第一次使用
item_ids
鍵執行此incr
呼叫時,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: Run Python File in Terminal 命令。
請注意,這應該謹慎操作,因為它將刪除當前資料庫中的所有鍵,如果在生產環境中操作,可能會導致資料丟失。
可選:建立 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 應用服務。
您還可以檢視這些其他 VS Code Python 文章