Visual Studio Code での FastAPI チュートリアル
FastAPI は、Python で API を構築するためのモダンで高性能な Web フレームワークです。API を迅速かつ効率的に構築できるように設計されており、自動検証、シリアライズ、API ドキュメントの自動生成などの機能を提供するため、Web サービスやマイクロサービスの構築で人気のある選択肢となっています。
この FastAPI チュートリアルでは、FastAPI を使用して買い物リストアプリを作成します。チュートリアルの最後には、Visual Studio Code のターミナル、エディター、デバッガーを使用して FastAPI を操作する方法を理解できるようになります。このチュートリアルは FastAPI の詳細な解説を目的としたものではありません。詳細については、FastAPI 公式ドキュメントを参照してください。
Python を初めて使用する場合は、言語や VS Code の Python サポートに慣れるために、まず私たちの Python チュートリアルから始めることをお勧めします。このチュートリアルは、すでに Python に慣れており、VS Code で FastAPI を扱う方法を学びたい方に適しています。
この FastAPI チュートリアルで完成したコードプロジェクトは、GitHub の python-sample-vscode-fastapi-tutorial にあります。
問題が発生した場合は、Python 拡張機能のディスカッション Q&Aで回答を検索したり、質問したりできます。
プロジェクトのセットアップ
本チュートリアルに向けてプロジェクトをセットアップする方法はいくつかあります。ここでは、GitHub Codespaces を使用する方法と、ローカルマシンの VS Code でセットアップする方法を解説します。
GitHub Codespaces
プロジェクトを GitHub Codespaces で開発するようにセットアップできます。これを使うと、codespace 内でリモートからコーディング、デバッグ、アプリの実行が可能になります。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 を選択して、ワークスペースが必要なリソースや拡張機能にアクセスできるようにします。Workspace Trust の詳細については、ドキュメントを参照してください。
次に、アプリケーションでインストールしたい依存関係をリストした requirements.txt ファイルを作成しましょう。requirements.txt ファイルは Python 開発における一般的な慣習であり、プロジェクトが依存するライブラリとそのバージョンを指定するために使用されます。このファイルは、プロジェクトに関わる誰でも同様の開発環境を再現できるようにし、一貫性を維持するために役立ちます。
アプリ作成のために FastAPI、サーバーとして uvicorn、データストレージの処理と Redis データベースとの通信のために Redis および type-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 を選択します。
-
groceries-pluginフォルダーにmain.pyとして保存(⇧⌘S (Windows, Linux Ctrl+Shift+S))します。 -
以下のコードを
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)を使用してデバッガーを再起動します。 -
ターミナル内の
http://127.0.0.1:8000/URL を Ctrl+Click して、デフォルトのブラウザーでそのアドレスを開きます。
おめでとうございます!FastAPI アプリが起動しました!
-
デバッグツールバーの Stop ボタン、または ⇧F5 (Windows, Linux Shift+F5) を使用してデバッガーを停止します。
買い物リストアイテム用のモデルを作成
FastAPI アプリが動作するようになったので、Pydantic を使用して買い物リストのアイテムを定義できます。Pydantic は、FastAPI とシームレスに統合されるデータ検証および解析ライブラリです。Pydantic を使用すると、API リクエスト内の受信データ(「ペイロード」と呼ばれます)を自動的に検証・解析するために、型ヒントを使用した Python クラスとしてデータモデルを定義できます。
買い物リストのアイテム用のモデルを作成しましょう。ItemPayload モデルを使用して、リストに追加するアイテムのデータ構造を定義します。このモデルには item_id、item_name、quantity の3つのフィールドを持たせます。
-
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
VS Code のデフォルトの Python 言語サーバーである Pylance は、Pydantic モデルや FastAPI を操作するのに役立つ型ヒント機能をサポートしています。これは、Pylance が Python の静的型チェッカーである Pyright 上に構築されており、コード内の型エラーを検出してバグを防ぎ、コード品質を向上させることができるためです。
以下の3つのステップはオプションですが、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 アプリケーションで定義されたメタデータと型ヒントに基づいて動的に生成されます。 -
行番号の左側の余白をクリックするか(F9)、
if quantity <= 0文の横にブレークポイントを追加します。デバッガーはその行の実行前に停止するため、コードを一行ずつ検査できます。
-
デバッガー(F5)を開始し、ブラウザーで
http://127.0.0.1:8000/docsにアクセスします。アプリで利用可能な2つのエンドポイント(
/itemsとルート/)を備えた Swagger インターフェイスが表示されるはずです。
-
/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と評価されます。デバッグコンソールは、式を素早くテストし、ブレークポイント時点でのコードの状態をよりよく理解するための強力なツールです。関数を呼び出したり変数を表示したりするなど、任意のコードを実行することもできます。VS Code での Python デバッグの詳細については、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 で作業している場合、Redis は Docker コンテナー または GitHub Codespace を設定することで利用できます。このチュートリアルでは Docker コンテナーを使用しますが、GitHub Codespace のセットアップ方法については上記のセクションを参照してください。
それ以外の場合、Linux または macOS マシンを使用しているなら、公式サイトの指示に従って Redis をインストールし、その後 データベースの置換 セクションに進んでください。
Windows での Docker コンテナーのセットアップ
VS Code の Dev Containers 拡張機能は、プロジェクトとその依存関係、および必要なすべてのツールを1つの tidy なコンテナーに統合するための合理化されたアプローチを提供し、フル機能の開発環境を作成します。この拡張機能を使用すると、プロジェクトをコンテナー内(またはマウントされたコンテナー)で開き、そのフル機能セットを使用できます。
以下の手順では、マシンに以下の要件がインストールされていることを確認してください。
要件
Dev コンテナー構成を作成する
-
コマンドパレットを開き、Dev Containers: Add Dev Container Configuration Files… を実行します。
-
Python 3 を選択します。

-
デフォルトのバージョンを選択します。
-
追加機能としてインストールするものに Redis Server を選択し、OK を押し、次に Keep Defaults を選択します。
オプションでコンテナーに含める機能 (Features) をインストールできます。本チュートリアルでは、Redis 用の適切な dev コンテナー設定をインストールして追加するコミュニティ貢献機能である Redis Server をインストールします。

これにより、ワークスペースに
.devcontainerフォルダーとdevcontainer.jsonファイルが作成されます。このファイルを編集して、コンテナーのセットアップに VS Code 拡張機能やプロジェクトの依存関係のインストール手順が含まれるようにしましょう。 -
devcontainer.jsonファイルを開きます。 -
"features" : { ... }エントリの後に「,」を追加し、ファイルに設定を追加できるようにします。次に、
devcontainer.jsonファイルのpostCreateCommandプロパティに必要な依存関係インストールコマンドを追加して、コンテナーのセットアップ完了後にアプリケーションを実行できるようにします。 -
以下のコンテンツを見つけ、その行のコメント(
//)を削除して、コンテナー作成時に依存関係がインストールされるようにします。"postCreateCommand": "pip3 install --user -r requirements.txt",postCreateCommandやその他のライフサイクルスクリプトの詳細については、Development Containers Specification を参照してください。次に、
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 コンテナーの構成の詳細については、Dev Containers ドキュメントを参照してください。
完了すると、Python 3 と Redis Server がインストールされた、完全に構成済みの Linux ベースのワークスペースが用意されます。
コンテナーがセットアップされると、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 ハッシュを使用してデータを保存します。
ID を知らなくてもアイテムを取得できる従来のデータベースとは異なり、Redis ハッシュから値を取得するにはハッシュキーを知る必要があります。このチュートリアルでは、アイテムを名前で取得して ID にマッピングするために item_name_to_id というハッシュを作成します。さらに、ID でアイテムを取得し、名前と数量にマッピングするために他のハッシュを作成します。各アイテムハッシュは item_id:{item_id} と名付けられ、item_name と quantity の2つのフィールドを持ちます。
まず、辞書を 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)Redis がまだインポートされていないため、Pylance がエラーメッセージを表示します。
-
エディターで「redis」にカーソルを合わせ、表示された電球をクリックするか(⌘. (Windows, Linux Ctrl+.))、Add 'import redis' を選択します。

ヒント: Pylance が自動的にインポートを追加するように設定できます。設定エディター(⌘, (Windows, Linux Ctrl+,))で Auto Import Completions 設定を探し、有効にしてください。
これで、ローカルホスト(
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 にマッピングしていると仮定します(このコードはすぐに後で追加します!)。リクエストで受け取ったアイテム名の ID は、Redis のhgetメソッドを呼び出すことで取得できます。これにより、要求された名前がハッシュに存在する場合はアイテム 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に変更します。 -
インラインヒントが有効な場合、
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 を名前や数量にマッピングするためにも、ID での取得を容易にするために"item_id:{item_id}"をハッシュ名として使用し、アイテムごとに個別の Redis ハッシュを作成します。各ハッシュには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ルートを操作してアプリケーションをテストします。完了したらデバッガーを停止してください。
おめでとうございます!買い物リストへのアイテム追加、リスト表示、削除を行うルートを備え、データが Redis データベースに永続化される、動作する FastAPI アプリケーションが完成しました。
オプション:データベース削除のセットアップ
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 の詳細については、公式ドキュメントを参照してください。
本番 Web サイトでアプリを試すには、チュートリアル Docker コンテナーを使用して Azure App Service に Python アプリをデプロイする を確認してください。
その他の VS Code Python 記事も確認できます。