PythonでAPI開発するならFastAPI!入門から基本まで
現代のソフトウェア開発において、API (Application Programming Interface) は不可欠な要素となっています。異なるシステム間でのデータのやり取り、フロントエンドとバックエンドの連携、マイクロサービスの構築など、様々なシーンでAPIが活躍しています。
Pythonは、その書きやすさ、豊富なライブラリ、そして多様な用途への適応性から、バックエンド開発、特にAPI開発においても非常に人気の高い言語です。Pythonには歴史あるFlaskやDjangoといったWebフレームワークがありますが、近年、特にAPI開発の分野で注目を集めているのが FastAPI です。
本記事では、なぜ今FastAPIが選ばれるのか、その基本的な使い方からAPI開発の重要な概念までを、ステップバイステップで詳細に解説していきます。Pythonを使ったAPI開発に興味がある方、FlaskやDjango以外の選択肢を探している方にとって、FastAPIの魅力と実力を理解し、実際にAPIを開発するための第一歩を踏み出す手助けとなることを目指します。
さあ、FastAPIの世界へ飛び込みましょう!
1. はじめに:なぜPythonでAPI開発? そしてなぜFastAPI?
1.1 APIとは何か、その重要性
API(Application Programming Interface)は、あるソフトウェアの機能やデータを、外部の別のソフトウェアから利用するための窓口です。Webの世界では、HTTPプロトコルを使ってデータの送受信を行うWeb APIが一般的です。例えば、スマートフォンのアプリがサーバーから最新情報を取得したり、異なるサービスが連携して機能を提供したりする際に、APIが利用されています。
APIは、システム間の結合度を低く保ちつつ連携を可能にするため、大規模なシステム開発やマイクロサービスアーキテクチャにおいて非常に重要な役割を果たします。また、フロントエンド(Webブラウザやモバイルアプリ)とバックエンド(サーバーサイドのロジックやデータベース)を分離して開発する際にも、APIは両者をつなぐ明確なインターフェースとなります。
1.2 PythonとWebフレームワークの選択肢
Pythonは、その汎用性の高さから、Web開発においても広く利用されています。特に、以下のようなフレームワークがよく知られています。
- Django: フルスタックのWebフレームワークで、管理画面、ORM (Object-Relational Mapper)、テンプレートエンジンなど、Webアプリケーション開発に必要な多くの機能が揃っています。大規模なWebサイトやアプリケーション開発に適しています。
- Flask: マイクロフレームワークと呼ばれ、必要最小限の機能のみを提供します。軽量で柔軟性が高く、API開発や小規模なアプリケーション開発に適しています。拡張機能(Extension)を利用して機能を増やしていくスタイルです。
これらは素晴らしいフレームワークですが、RESTful APIのようなモダンなAPI開発において、FastAPIはいくつかの顕著な利点を持っています。
1.3 なぜ今、FastAPIなのか? FastAPIの登場と位置づけ
FastAPIは、2018年に登場した比較的新しいフレームワークです。Starlette(非同期HTTPフレームワーク)とPydantic(データバリデーションライブラリ)を基盤として構築されており、Pythonのモダンな機能(特に型ヒントと非同期処理)を最大限に活用しています。
FastAPIは、Flaskのような軽量さと、Djangoのような一部の高機能(特に自動ドキュメント生成やデータバリデーション)を兼ね備えつつ、API開発に特化した設計思想を持っています。特に以下のような点が、FastAPIをAPI開発において非常に魅力的な選択肢にしています。
- 高いパフォーマンス: Starletteによる非同期処理サポートと、Uvicornのような高速なASGIサーバーとの組み合わせにより、非常に高いスループットを実現します。これは、I/Oバウンドな処理(データベースアクセス、外部API呼び出しなど)が多いAPIにおいて大きな利点となります。
- 開発速度の向上: Pythonの標準的な型ヒントを使用することで、コードの補完、エラーチェック、データバリデーション、データのシリアライズ(PythonオブジェクトからJSONへの変換など)とデシリアライズ(JSONからPythonオブジェクトへの変換)が自動で行われます。これにより、開発者はデータ処理のコードを大幅に削減でき、ロジックの実装に集中できます。
- 自動ドキュメント生成: OpenAPI(旧Swagger)およびJSON Schema標準に準拠しており、Pythonの型ヒントやPydanticモデルから、APIの仕様ドキュメント(Swagger UIやReDoc)を自動生成します。API利用者だけでなく開発者自身にとっても、APIの仕様を常に最新かつ正確に把握できることは大きなメリットです。
- 堅牢なデータバリデーション: Pydanticを内部で利用しているため、リクエストデータのバリデーションとシリアライズ/デシリアライズが自動で強力に行われます。不正なデータ形式や必須フィールドの欠如などを簡単にチェックできます。
- 依存性注入システム: コードの再利用性を高め、テストを容易にするための依存性注入(Dependency Injection)システムが組み込まれています。共通の処理(認証、データベースセッションの取得など)を効果的に管理できます。
- 非同期処理(async/await)のサポート: Python 3.6以降で導入された
async
/await
構文をネイティブにサポートしており、ノンブロッキングI/Oを利用した効率的な並行処理を記述できます。
これらの特徴から、FastAPIは特にモダンなWeb API、マイクロサービス、あるいは高性能が求められるバックエンドサービスをPythonで開発する際に、非常に強力なツールとなっています。
1.4 記事の概要
本記事では、FastAPIを使ったAPI開発の基本を、以下のステップで解説します。
- FastAPIの主要な概念と特徴を理解する。
- 開発環境を準備する。
- 最小構成のFastAPIアプリケーションを作成・実行する。
- ルーティング、パス/クエリパラメータ、リクエストボディの扱い方を学ぶ。
- Pydanticモデルを使ったデータバリデーションとシリアライズを習得する。
- 応答モデルでAPIの応答を定義する。
- エラーハンドリングの方法を知る。
- 依存性注入システムを活用する。
- 自動生成されるAPIドキュメントを利用する。
- 簡単なテストの方法を知る。
これらの基本的な要素を習得することで、あなたのPythonでのAPI開発スキルは大きく向上するはずです。
2. FastAPIとは何か:その主要な特徴を深掘り
FastAPIは、Pythonの以下の要素を組み合わせることで、その能力を発揮しています。
- Starlette: ASGI (Asynchronous Server Gateway Interface) フレームワーク。軽量で高速な非同期HTTPリクエスト/レスポンス処理を提供します。
- Pydantic: Pythonの型ヒントに基づくデータバリデーション、シリアライズ、デシリアライズライブラリ。構造化されたデータの定義と検証を容易にします。
- Pythonの型ヒント: Python 3.5以降で導入された機能で、変数、関数引数、戻り値などの型を示すために使用されます。IDEによるコード補完や静的解析ツールによるエラー検出に役立ちます。FastAPIはこれをデータ定義やバリデーション、ドキュメント生成に活用します。
- asyncio: Pythonの標準ライブラリで、非同期処理を記述するためのフレームワークです。FastAPIは
async
/await
構文を通じてasyncio
を利用し、高い並行処理能力を実現します。
これらの技術要素が組み合わさることで、FastAPIは以下の主要な特徴を備えています。
2.1 高いパフォーマンス (Starlette, Uvicorn)
FastAPIは、ASGIという新しい標準仕様に基づいています。従来のWSGI (Web Server Gateway Interface) が同期的な処理を前提としていたのに対し、ASGIは非同期処理をサポートしています。これにより、データベースへのクエリ待ちや外部API呼び出し待ちといったI/O処理中に他のリクエストを処理することが可能になり、より高いスループットを実現できます。
FastAPIアプリケーションを実行するには、UvicornやHypercornといったASGIサーバーが必要です。Uvicornは特に高速なサーバーとして知られており、FastAPIと組み合わせることで、NodeJSやGoといった言語で書かれたフレームワークに匹敵、あるいはそれ以上のパフォーマンスを発揮することもあります。
2.2 Python標準の型ヒントに基づく自動機能
FastAPIの最も革新的な特徴の一つが、Pythonの型ヒントを積極的に活用している点です。関数引数やPydanticモデルに型ヒントを付けるだけで、FastAPIは以下のことを自動で行います。
- データバリデーション: 受け取ったリクエストデータ(パスパラメータ、クエリパラメータ、リクエストボディ)が期待する型や形式に合っているかを自動で検証します。不正なデータであれば、適切なHTTPエラーレスポンスを返します。
- データシリアライズ/デシリアライズ: PythonオブジェクトとJSON形式のデータを自動で相互変換します。特に、Pydanticモデルで定義されたデータ構造に基づいて、複雑なオブジェクトの変換も容易に行います。
- ドキュメント生成: 型ヒントやPydanticモデルの定義、および追加のメタデータ(
description
,example
など)から、OpenAPI仕様に準拠したAPIドキュメントを自動生成します。
これにより、開発者はデータ処理やバリデーションのための冗長なコードを書く必要がなくなり、APIのビジネスロジックの実装に集中できます。
2.3 非同期処理 (async
/await
) のサポート
FastAPIはPythonのasync
/await
構文を完全にサポートしています。パスオペレーション関数をasync def
で定義することで、非同期処理を行うことができます。
“`python
from fastapi import FastAPI
app = FastAPI()
@app.get(“/async-endpoint”)
async def read_async_endpoint():
# データベースアクセスや外部API呼び出しなど、
# 時間のかかるI/O処理を非同期で行うことができる
await some_async_operation()
return {“message”: “This was an asynchronous operation”}
“`
これにより、APIが多数のI/Oバウンドな操作を含む場合でも、効率的にリクエストを並行処理し、全体のパフォーマンスを向上させることができます。もちろん、同期的な処理が必要な場合は、通常のdef
で関数を定義することも可能です。FastAPIは、必要に応じて内部でスレッドプールを使用して同期的な処理を非同期的に実行します。
2.4 OpenAPIおよびJSON Schemaへの準拠
FastAPIは、RESTful APIの標準仕様であるOpenAPI仕様(かつてのSwagger仕様)と、データ構造定義の標準であるJSON Schemaに完全に準拠しています。これにより、FastAPIで開発したAPIは、これらの標準をサポートする様々なツールやサービス(APIゲートウェイ、コード生成ツール、APIドキュメント閲覧ツールなど)と容易に連携できます。
特に、FastAPIが自動生成するAPIドキュメントは、OpenAPI仕様に基づいています。
2.5 シンプルで直感的な記述
FastAPIのAPI定義は非常にシンプルで直感的です。デコレータを使ってHTTPメソッドとパスを定義し、通常のPython関数としてリクエストハンドラ(パスオペレーション関数)を記述します。関数引数に型ヒントを付けるだけで、パラメータやリクエストボディの受け取り、バリデーションが自動で行われます。
“`python
from fastapi import FastAPI
app = FastAPI()
@app.get(“/items/{item_id}”)
def read_item(item_id: int, q: str | None = None):
# item_id は自動的に int に変換され、q は str または None
return {“item_id”: item_id, “q”: q}
“`
このように、冗長な設定ファイルや複雑なクラス定義なしに、Pythonの標準的な構文を使ってAPIエンドポイントを定義できます。
2.6 依存性注入システム
FastAPIには、組み込みの強力な依存性注入(Dependency Injection: DI)システムがあります。これにより、複数のパスオペレーション関数で共通して使用されるロジック(認証、データベース接続、設定値の読み込みなど)を関数として定義し、それを依存関係としてパスオペレーション関数に注入できます。
“`python
from fastapi import Depends, FastAPI
app = FastAPI()
async def get_current_user(token: str = Depends(oauth2_scheme)): # oauth2_schemeは認証の実装
# トークンを検証してユーザーを取得するロジック
user = await authenticate_user(token)
if not user:
raise HTTPException(status_code=401, detail=”Invalid authentication credentials”)
return user
@app.get(“/users/me”)
async def read_users_me(current_user: User = Depends(get_current_user)):
# get_current_user の戻り値が current_user として注入される
return current_user
“`
DIシステムを利用することで、コードのモジュール化が進み、テストが容易になり、共通処理の変更が容易になります。
3. 開発環境の準備
FastAPIを使った開発を始めるには、Pythonの実行環境が必要です。
3.1 Pythonのインストール
FastAPIはPython 3.8以上のバージョンを推奨しています。Pythonがインストールされていない場合は、公式ウェブサイトからダウンロードしてインストールしてください。
インストールが完了したら、ターミナル(コマンドプロンプト)で以下のコマンドを実行し、Pythonのバージョンを確認できます。
“`bash
python –version
または
python3 –version
“`
3.2 仮想環境の利用(推奨)
Pythonプロジェクトを開発する際は、他のプロジェクトとの依存関係の衝突を防ぐために、仮想環境(Virtual Environment)を使用することが強く推奨されます。仮想環境は、プロジェクトごとに独立したPythonの実行環境とライブラリ管理領域を提供します。
Python 3.3以降には、標準ライブラリとしてvenv
モジュールが付属しています。これを利用するのが最も手軽です。
- プロジェクトディレクトリを作成し、移動する:
bash
mkdir myapi
cd myapi - 仮想環境を作成する:
bash
python -m venv venv
# または
python3 -m venv venv
これにより、myapi
ディレクトリ内にvenv
という名前のディレクトリが作成され、その中に仮想環境が構築されます。 - 仮想環境をアクティベート(有効化)する:
- macOS/Linux:
bash
source venv/bin/activate - Windows (コマンドプロンプト):
bash
venv\Scripts\activate.bat - Windows (PowerShell):
bash
venv\Scripts\Activate.ps1
仮想環境が有効になると、ターミナルのプロンプトの先頭に(venv)
のような仮想環境名が表示されます。
- macOS/Linux:
- 仮想環境をディアクティベート(無効化)する:
作業が完了したら、以下のコマンドで仮想環境を終了できます。
bash
deactivate
venv
以外にも、より高機能なプロジェクト・依存関係管理ツールとしてPoetry
やpipenv
などがありますが、最初はvenv
で十分です。
3.3 FastAPIとUvicornのインストール
仮想環境をアクティベートした状態で、FastAPIとASGIサーバーであるUvicornをインストールします。
bash
pip install fastapi uvicorn[standard]
fastapi
: FastAPIフレームワーク本体。uvicorn[standard]
: Uvicornサーバー。[standard]
を指定することで、必要な追加ライブラリ(例:httptools
,uvloop
など)も一緒にインストールされ、パフォーマンスが最適化されます。
これで、FastAPIアプリケーションを開発・実行するための環境が整いました。
4. FastAPIアプリケーションの作成(最小構成)
それでは、FastAPIを使った最初のアプリケーションを作成してみましょう。慣習として、メインのファイル名をmain.py
とすることが多いです。
-
main.py
ファイルの作成:
プロジェクトディレクトリ(myapi
)にmain.py
という名前のファイルを作成し、以下のコードを記述します。“`python
main.py
from fastapi import FastAPI
FastAPIインスタンスを作成
このインスタンスが全てのAPIエンドポイント(パスオペレーション)を管理します
app = FastAPI()
HTTP GETリクエストをルートパス(“/”)で受け付けるエンドポイントを定義
@app.get(“/”)
パスオペレーション関数を定義
この関数がリクエストを受け取った際に実行されます
def read_root():
# 戻り値は自動的にJSONにシリアライズされます
return {“Hello”: “World”}
“` -
アプリケーションの実行:
仮想環境がアクティベートされたターミナルで、以下のコマンドを実行します。bash
uvicorn main:app --reloadコマンドの意味は以下の通りです。
*uvicorn
: Uvicornサーバーを起動します。
*main:app
: 実行するFastAPIアプリケーションを指定します。「main
モジュール(main.py
ファイル)の中にあるapp
という名前のオブジェクト」を意味します。
*--reload
: 開発中にコードを変更した際に、サーバーを自動的に再起動します。開発効率を向上させるため、開発中は常にこのオプションを付けることを推奨します。サーバーが起動すると、以下のような出力が表示されます。
INFO: Will watch for changes in these directories: ['/path/to/your/myapi']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [xxxxx] using statreload
INFO: Started server running in loop asyncio
INFO: Waiting for application startup.
INFO: Application startup complete.これで、FastAPIアプリケーションが
http://127.0.0.1:8000
で実行されています。 -
動作確認:
Webブラウザを開き、http://127.0.0.1:8000
にアクセスしてみてください。画面に{"Hello":"World"}
と表示されれば成功です。あるいは、ターミナルで
curl
コマンドを使用しても確認できます。bash
curl http://127.0.0.1:8000出力:
json
{"Hello":"World"}これで、最小構成のFastAPIアプリケーションが完成しました。
5. ルーティングとパスオペレーション
FastAPIでは、特定のURLパスとHTTPメソッドの組み合わせに対して、実行する関数(パスオペレーション関数またはエンドポイント関数)を関連付けます。このプロセスをルーティングと呼びます。
5.1 HTTPメソッド
Web APIでは、リソースに対してどのような操作を行うかを示すためにHTTPメソッドを使用します。主なメソッドは以下の通りです。
- GET: リソースを取得する。
- POST: 新しいリソースを作成する。
- PUT: 既存のリソース全体を更新する。
- PATCH: 既存のリソースの一部を更新する。
- DELETE: リソースを削除する。
- OPTIONS: リソースがサポートしているHTTPメソッドを取得する(主にCORSで使用)。
- HEAD: GETと同様だが、応答ボディを含まない(ヘッダーのみ取得)。
5.2 パスオペレーションデコレータ
FastAPIでは、FastAPI
インスタンスのメソッドとして、各HTTPメソッドに対応するデコレータが用意されています。
@app.get("/path")
@app.post("/path")
@app.put("/path")
@app.delete("/path")
@app.options("/path")
@app.head("/path")
@app.patch("/path")
これらのデコレータを使って、その直下に定義する関数が、指定されたパスとHTTPメソッドに対応するパスオペレーション関数であることをFastAPIに伝えます。
“`python
main.py
from fastapi import FastAPI
app = FastAPI()
@app.get(“/”)
def read_root():
return {“message”: “Welcome!”}
@app.post(“/items/”)
def create_item(item: dict): # リクエストボディを受け取る(詳細は後述)
return {“message”: “Item created”, “item”: item}
@app.get(“/items/{item_id}”)
def read_item(item_id: int): # パスパラメータを受け取る(詳細は後述)
return {“item_id”: item_id}
@app.put(“/items/{item_id}”)
def update_item(item_id: int, item: dict): # パスパラメータとリクエストボディ
return {“message”: f”Item {item_id} updated”, “item”: item}
“`
5.3 関数定義と非同期関数 (async def
)
パスオペレーション関数は、通常のPython関数として定義します。非同期処理を行いたい場合は、async def
で定義します。
“`python
@app.get(“/sync-endpoint”)
def sync_operation():
# 同期的な処理
return {“result”: “sync”}
@app.get(“/async-endpoint”)
async def async_operation():
# 非同期的な処理 (例: await asyncio.sleep(1))
return {“result”: “async”}
“`
同期的な関数は、FastAPIが内部でスレッドプールを使って非同期的に実行するように処理されるため、同期的な処理しか含まないエンドポイントでもdef
を使用しても問題ありません。ただし、I/Oバウンドな処理(データベースアクセス、外部API呼び出しなど)を含む場合は、async def
を使って非同期的に記述することで、パフォーマンスを最大限に引き出すことができます。
5.4 基本的な応答の返し方
パスオペレーション関数が返す値は、自動的にJSON形式に変換されてHTTPレスポンスのボディとして返されます。辞書 (dict
)、リスト (list
)、PydanticモデルのインスタンスなどがJSONにシリアライズされます。文字列 (str
) や数値 (int
, float
) もそのまま返すことができます。
“`python
@app.get(“/json_example”)
def get_json():
return {“name”: “FastAPI”, “version”: “0.1”}
@app.get(“/list_example”)
def get_list():
return [1, 2, 3, 4, 5]
@app.get(“/string_example”)
def get_string():
return “Hello, FastAPI!”
“`
FastAPIは、デフォルトでContent-Type: application/json
ヘッダーを付けてJSON応答を返します。他の形式(例: HTML、Plain Text)を返したい場合は、fastapi.responses
モジュールにある適切なクラス(例: HTMLResponse
, PlainTextResponse
)を使用します。
“`python
from fastapi.responses import HTMLResponse
@app.get(“/html_example”, response_class=HTMLResponse)
def get_html():
return “””
Hello, FastAPI!
“””
“`
response_class
引数を使用することで、応答の形式を制御できます。
6. パスパラメータ
APIのパスの一部としてデータを渡したい場合があります。例えば、特定の商品 (/items/123
) や特定のユーザー (/users/john_doe
) を指定したい場合などです。これをパスパラメータと呼びます。
FastAPIでは、パスの定義時に波括弧 {}
を使ってパスパラメータを指定し、パスオペレーション関数の引数として同名のパラメータを受け取ることで、パスパラメータを簡単に利用できます。
“`python
main.py
from fastapi import FastAPI
app = FastAPI()
パスパラメータとして item_id を定義
@app.get(“/items/{item_id}”)
関数引数として item_id を受け取る
型ヒント int を付ける
def read_item(item_id: int):
# item_id は自動的に整数に変換されて渡される
return {“item_id”: item_id}
“`
このエンドポイントに対して、例えば/items/5
というURLでGETリクエストを送ると、read_item
関数が実行され、item_id
引数には整数値の5
が渡されます。
6.1 型ヒントによる自動型変換とバリデーション
FastAPIは、パスパラメータの型ヒントを見て、自動的にデータ型を変換しようとします。上記の例では、item_id: int
としているため、URLから抽出された文字列 "5"
は自動的に整数 5
に変換されます。
もし /items/abc
のように、int
に変換できない値が渡された場合、FastAPIは自動的にクライアントに対して422 Unprocessable Entityエラーレスポンスを返します。これは、item_id
が整数であることをFastAPIが検証しているからです。
サポートされている標準的な型ヒント(int
, float
, str
, bool
, uuid
, datetime
, date
, time
, timedelta
など)は、自動的に適切な型に変換・検証されます。
6.2 複数のパスパラメータ
複数のパスパラメータを定義することも可能です。
python
@app.get("/users/{user_id}/items/{item_id}")
def read_user_item(user_id: int, item_id: int):
return {"user_id": user_id, "item_id": item_id}
6.3 定義順序に注意
もし/users/me
のような固定パスと、/users/{user_id}
のようなパスパラメータを含むパスを両方定義したい場合、より具体的なパスである/users/me
を先に定義する必要があります。
“`python
@app.get(“/users/me”) # 具体的なパスを先に定義
def read_users_me():
return {“user_id”: “current user”}
@app.get(“/users/{user_id}”) # パスパラメータを含むパスを後に定義
def read_user(user_id: int):
return {“user_id”: user_id}
“`
もし定義順が逆だと、/users/me
へのリクエストが/users/{user_id}
の方にマッチしてしまい、"me"
がuser_id
として渡されてしまう可能性があります。
7. クエリパラメータ
APIには、パスパラメータの他に、URLの末尾に?
に続いてkey=value
の形式で渡されるクエリパラメータもあります。複数のクエリパラメータは&
で連結します。例えば、/items/?skip=0&limit=10
のように、リストのページングやフィルタリング条件を指定するためによく使われます。
FastAPIでは、パスオペレーション関数の引数として、パスパラメータとして定義されていない引数を定義することで、クエリパラメータを受け取ることができます。
“`python
main.py
from fastapi import FastAPI
app = FastAPI()
パスパラメータ item_id に加えて、クエリパラメータ skip, limit を定義
@app.get(“/items/{item_id}”)
item_id はパスパラメータ
skip, limit はクエリパラメータとして扱われる
def read_item(item_id: int, skip: int = 0, limit: int = 10):
return {“item_id”: item_id, “skip”: skip, “limit”: limit}
“`
この例では、item_id
はパスパラメータとして定義されているのでパスから取得されます。skip
とlimit
はパスパラメータとして定義されていないため、クエリパラメータとして扱われます。
7.1 オプションのクエリパラメータとデフォルト値
パスオペレーション関数の引数にデフォルト値を設定すると、その引数はオプションのクエリパラメータとして扱われます。上記の例では、skip
とlimit
にはそれぞれ0
と10
というデフォルト値が設定されているため、これらのクエリパラメータが省略されてもエラーにならず、デフォルト値が使用されます。
デフォルト値がない引数は、必須のクエリパラメータとして扱われます。必須クエリパラメータがリクエストに含まれていない場合、FastAPIは422エラーを返します。
“`python
@app.get(“/items/”)
q は必須のクエリパラメータ
optional_q はオプションのクエリパラメータ (デフォルト値 None)
def read_items(q: str, optional_q: str | None = None):
results = {“items”: [{“item_id”: “Foo”}, {“item_id”: “Bar”}]}
if q:
results.update({“q”: q})
if optional_q:
results.update({“optional_q”: optional_q})
return results
“`
この例では、/items/?q=somequery
のように q
クエリパラメータが必須ですが、optional_q
は省略可能です。optional_q: str | None = None
のように、型ヒントに | None
(Python 3.10以降) または Optional[str]
(typingモジュールからimport) を使い、デフォルト値を None
にすることで、オプションであることを明示的に示せます。
7.2 型ヒントによる型変換とバリデーション
パスパラメータと同様に、クエリパラメータにも型ヒントを付けることで、FastAPIは自動的に型変換とバリデーションを行います。例えば、skip: int
としている場合、クエリパラメータskip
の値は自動的に整数に変換され、変換できない場合は422エラーとなります。
7.3 複数のクエリパラメータ
パスパラメータとクエリパラメータは組み合わせて使用できます。関数引数として定義する順番は関係ありません。
python
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None, short: bool = False):
item = {"item_id": item_id}
if q:
item.update({"q": q})
if not short:
item.update(
{"description": "This is an amazing item that has a long description"}
)
return item
この例では、item_id
はパスパラメータ、q
とshort
はクエリパラメータとして扱われます。short: bool = False
のようにbool
型を指定すると、クエリパラメータの値として"true"
, "True"
, "1"
, "on"
, "yes"
などが自動的にTrue
に変換されます(大文字小文字は区別されない)。
8. リクエストボディ
HTTPのPOST、PUT、PATCHメソッドなどでは、リクエストの本文(ボディ)にデータを含めて送信することがよくあります。API開発では、クライアントからJSON形式のデータを受け取ることが一般的です。FastAPIでは、リクエストボディのデータを簡単に受け取り、バリデーションすることができます。
FastAPIでリクエストボディを受け取るには、関数の引数として、Pydanticモデルのインスタンスを指定します。
8.1 Pydanticモデルの導入
Pydanticは、Pythonの型ヒントを使ってデータの構造を定義し、その構造に基づいたデータのバリデーション、シリアライズ、デシリアライズを行うライブラリです。FastAPIはPydanticを内部で利用しており、リクエストボディの定義にPydanticモデルを使用することを推奨しています。
Pydanticモデルを作成するには、pydantic
モジュールからBaseModel
をインポートし、それを継承したクラスを定義します。クラスの属性として、期待するデータフィールド名とその型ヒントを記述します。
“`python
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None # オプション (デフォルト値 None)
price: float
tax: float | None = None # オプション (デフォルト値 None)
“`
このItem
モデルは、name
(文字列)、description
(オプションの文字列)、price
(浮動小数点数)、tax
(オプションの浮動小数点数) という構造を持つデータを表現します。description
やtax
のようにデフォルト値がある属性は、データに含まれていなくてもエラーになりません。
8.2 Pydanticモデルを使ったリクエストボディの受け取り
パスオペレーション関数の引数として、定義したPydanticモデルの型ヒント付きでパラメータを指定します。
“`python
main.py
from fastapi import FastAPI
from pydantic import BaseModel # Pydanticをインポート
Itemモデルを定義
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
POST /items/ エンドポイントを定義
@app.post(“/items/”)
リクエストボディを Item クラスのインスタンスとして受け取る
item: Item で型ヒントを指定
async def create_item(item: Item):
# 受け取った item オブジェクトは Item モデルのインスタンス
# データは既にバリデーション済み
item_dict = item.model_dump() # Pydantic v2.0 以降は model_dump(), 以前は dict()
if item.tax:
price_with_tax = item.price + item.tax
item_dict.update({“price_with_tax”: price_with_tax})
return item_dict
“`
このエンドポイントに対して、クライアントから以下のようなJSONデータをPOSTリクエストのボディとして送信したとします。
json
{
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.4
}
FastAPIは、以下の処理を自動で行います。
- リクエストボディからJSONデータを読み込む。
- JSONデータをPydanticモデル
Item
の構造に従ってデシリアライズ(Pythonの辞書に変換し、さらにItem
インスタンスを作成)しようとする。 - この際、データの型や必須フィールドの有無などを
Item
モデルの定義に基づいてバリデーションする。 - バリデーションが成功した場合、
Item
インスタンスがcreate_item
関数のitem
引数に渡される。 - バリデーションが失敗した場合(例:
name
フィールドがない、price
が数値でないなど)、FastAPIは自動的に422 Unprocessable Entityエラーと、エラーの詳細を示すJSONボディを含むレスポンスをクライアントに返す。
このように、Pydanticモデルと型ヒントを使うだけで、リクエストボディの受け取り、デシリアライズ、バリデーションといった面倒な処理をすべてFastAPIに任せることができます。
8.3 ネストされたモデル
Pydanticモデルは、他のPydanticモデルを属性として持つことができます。これにより、複雑なネスト構造を持つJSONデータを扱うことができます。
“`python
from pydantic import BaseModel
class Address(BaseModel):
street: str
city: str
zip_code: str
class User(BaseModel):
name: str
email: str
address: Address # Address モデルを属性として持つ
@app.post(“/users/”)
async def create_user(user: User):
return user
“`
この場合、以下のようなJSONデータを受け取ることが期待されます。
json
{
"name": "John Doe",
"email": "[email protected]",
"address": {
"street": "123 Main St",
"city": "Anytown",
"zip_code": "12345"
}
}
FastAPIは、ネストされた構造も自動的にバリデーションしてくれます。
8.4 リストとしてのリクエストボディ
リクエストボディとして、Pydanticモデルのリストを受け取ることも可能です。
“`python
from typing import List # typingモジュールからListをインポート
@app.post(“/items/bulk/”)
リクエストボディを Item モデルのリストとして受け取る
async def create_items_bulk(items: List[Item]):
return {“created_count”: len(items), “items”: items}
“`
この場合、以下のようなJSONデータを受け取ることができます。
json
[
{
"name": "Item 1",
"price": 10.0
},
{
"name": "Item 2",
"price": 20.0,
"description": "Another item"
}
]
FastAPIはリスト内の各要素に対してもバリデーションを行います。
8.5 ボディとパス・クエリパラメータの組み合わせ
パスオペレーション関数は、パスパラメータ、クエリパラメータ、リクエストボディを組み合わせて受け取ることができます。それぞれのパラメータは、型ヒントを見て自動的に適切な場所(パス、クエリ文字列、ボディ)からデータが取得されます。
“`python
main.py
from fastapi import FastAPI, Path, Query # Path, Query をインポート
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.put(“/items/{item_id}”)
async def update_item(
*, # これ以降の引数はキーワード専用引数となり、順序指定が不要になる
item_id: int = Path(…, title=”The ID of the item to get”, ge=0, le=1000), # パスパラメータ + バリデーション
q: str | None = Query(None, alias=”item-query”), # クエリパラメータ + エイリアス
item: Item # リクエストボディ (Pydanticモデル)
):
results = {“item_id”: item_id, “item”: item}
if q:
results.update({“q”: q})
return results
“`
この例では:
* item_id
: パスパラメータ。Path
関数を使って追加のバリデーション(0以上1000以下)とドキュメント用の情報(title
)を追加しています。...
は、このパラメータが必須であることを示します(デフォルト値がないため元々必須ですが、Path
やQuery
を使う場合は明示的に指定することが多いです)。
* q
: クエリパラメータ。Query
関数を使ってデフォルト値(None
)と、実際のクエリパラメータ名としてitem-query
を使うエイリアスを設定しています。
* item
: リクエストボディ。Item
Pydanticモデルで定義された構造のJSONデータが期待されます。
パスオペレーション関数内でパスパラメータ、クエリパラメータ、ボディパラメータ、依存関係など、複数のタイプのパラメータを定義する場合、特にボディパラメータを最後に定義すると、引数の順序に関する混乱を避けるために、*
を使用して以降の引数をキーワード専用引数にすることが一般的です。
9. 応答モデル (Response Model)
FastAPIでは、APIからの応答データの構造も定義し、バリデーションやフィルタリングを自動で行うことができます。これは応答モデル(Response Model)機能を利用して行います。
9.1 なぜ応答モデルが必要か
応答モデルを使用する主な理由は以下の通りです。
- データの整形とフィルタリング: データベースから取得したオブジェクトなど、APIの応答として返したくない情報(パスワードハッシュなど)が含まれている場合があります。応答モデルで許可するフィールドだけを定義することで、不要な情報を自動的に削除し、必要な情報だけを返せます。
- 応答データのバリデーション: APIが返すデータが、定義したモデルの構造に合っているかをFastAPI自身に検証させることができます。
- 自動ドキュメントの強化: 応答モデルを定義することで、APIドキュメント(Swagger UI/ReDoc)にAPIがどのような構造の応答を返すかが正確に表示されます。これはAPI利用者にとって非常に役立ちます。
9.2 response_model
引数
応答モデルを指定するには、パスオペレーションデコレータ(@app.get
, @app.post
など)のresponse_model
引数に、応答データの構造を定義したPydanticモデルを指定します。
“`python
main.py
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
Itemのサブセットを定義するモデル
class ItemPublic(BaseModel):
name: str
price: float
app = FastAPI()
response_model に ItemPublic を指定
@app.post(“/items/”, response_model=ItemPublic)
async def create_item(item: Item):
# データベースにアイテムを作成するなどの処理…
# 例えば、ここではデータベースから取得した Item オブジェクトを返す想定
# 実際には item.tax などが含まれる可能性がある
return item # 返り値は Item モデルのインスタンスだが、response_model によってフィルタリングされる
“`
この例では、create_item
関数はリクエストで受け取ったItem
オブジェクトをそのまま返しています。しかし、response_model=ItemPublic
が指定されているため、FastAPIは返されるItem
オブジェクトをItemPublic
モデルに従って変換(シリアライズ)します。
結果として、クライアントにはItemPublic
モデルで定義されているname
とprice
フィールドのみを含むJSONが返され、description
やtax
フィールドは応答に含まれません。
json
{
"name": "Foo",
"price": 35.4
}
このように、response_model
を使うことで、実際のパスオペレーション関数の戻り値の構造に関わらず、APIの応答データの構造を厳密に制御できます。
9.3 リストの応答モデル
リストの応答モデルを定義する場合も同様に、response_model
にList[YourModel]
のようにtyping.List
を指定します。
“`python
from typing import List
from pydantic import BaseModel
class UserPublic(BaseModel):
id: int
name: str
サンプルデータ
fake_users_db = [
{“id”: 1, “name”: “Alice”, “hashed_password”: “…”} ,
{“id”: 2, “name”: “Bob”, “hashed_password”: “…”} ,
]
@app.get(“/users/”, response_model=List[UserPublic])
async def read_users():
# データベースからユーザーリストを取得する想定
# 各ユーザーオブジェクトには hashed_password が含まれている可能性がある
return fake_users_db # 返り値は dict のリストだが、List[UserPublic] によってフィルタリング・変換される
“`
この場合、fake_users_db
の各要素はUserPublic
モデルによってフィルタリングされ、id
とname
のみを含むJSON配列として返されます。hashed_password
は応答に含まれません。
9.4 response_model
の制限事項
response_model
は、返すオブジェクトの型ヒントとして使用するものではなく、返されるデータをPydanticモデルに変換・フィルタリングするためのものである点に注意してください。関数自体が返すオブジェクトの型は、response_model
で指定した型と異なっていても構いません(実際には、FastAPIが変換可能な型である必要があります)。
また、応答のHTTPステータスコードやカスタムヘッダーなどはresponse_model
では制御できません。これらを制御したい場合は、fastapi.responses
モジュールにあるクラス(例: JSONResponse
)を直接使用するか、HTTPException
を発生させるなどの方法をとります。
10. フォームデータとファイルのアップロード
Webアプリケーションでは、HTMLフォームから送信されるデータやファイルのアップロードを扱う必要があります。FastAPIはこれらの処理も簡単にサポートしています。
10.1 フォームデータの扱い (Form
)
標準的なHTMLフォーム(enctype="application/x-www-form-urlencoded"
または"multipart/form-data"
) から送信されるデータは、リクエストボディとして送信されますが、通常のJSONとは形式が異なります。FastAPIでは、fastapi
モジュールからForm
をインポートし、パスオペレーション関数の引数で型ヒントと共にForm
を指定することで、フォームデータを受け取ることができます。
“`python
main.py
from fastapi import FastAPI, Form
app = FastAPI()
@app.post(“/login/”)
async def login(username: str = Form(…), password: str = Form(…)):
# username と password はフォームデータから取得される
# Form(…) は必須フィールドであることを示す
return {“username”: username}
“`
このエンドポイントは、username
とpassword
というフィールドを含むフォームデータを受け付けます。Form(...)
のようにデフォルト値として...
(Ellipsis)を指定すると、そのフィールドが必須であることを示します。
10.2 ファイルのアップロード (UploadFile
)
ファイルのアップロードには、fastapi
モジュールからUploadFile
をインポートし、引数として指定します。UploadFile
はStarletteによって提供されるクラスで、アップロードされたファイルに関する情報(ファイル名、コンテンツタイプなど)とファイルの内容にアクセスするためのメソッド(read()
, write()
, seek()
など)を提供します。ファイルの内容はメモリ上に一時的に保持されるか、一定サイズを超えるとディスクに書き出されます。
“`python
main.py
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post(“/files/”)
async def create_file(file: UploadFile):
# file.filename: アップロードされたファイル名
# file.content_type: ファイルのMIMEタイプ
# file.file: ファイルオブジェクト(io.BytesIOまたは一時ファイル)
# file.read(): ファイル内容をバイト列として読み込む (非同期)
# file.write(): ファイル内容を書き込む (非同期)
# file.seek(0): ファイルポインタを先頭に戻す (非同期)
# file.close(): ファイルを閉じる (非同期)
# 例: ファイル内容を読み込んで返す
contents = await file.read()
return {"filename": file.filename, "content_type": file.content_type, "file_size": len(contents)}
@app.post(“/uploadfile/”)
async def create_upload_file(file: UploadFile):
# create_file と同様の機能
return {“filename”: file.filename}
“`
File
はUploadFile
の別名です。どちらを使っても構いません。
10.3 複数のファイルアップロード
複数のファイルを同時にアップロードする場合は、引数の型ヒントをList[UploadFile]
とします。
“`python
from typing import List
@app.post(“/uploadfiles/”)
async def create_upload_files(files: List[UploadFile]):
return [{“filename”: file.filename, “content_type”: file.content_type} for file in files]
“`
この場合、クライアントはmultipart/form-data
形式で、同じ名前(例えばfiles
)で複数のファイルを添付して送信する必要があります。
フォームデータ(Form
)とファイル(UploadFile
)は、リクエストボディとして送信されますが、JSONボディ(Pydanticモデル)とは同時に受け取ることはできません。これはHTTPプロトコルの仕様によるものです。ただし、パスパラメータやクエリパラメータとは組み合わせて受け取ることができます。
11. エラーハンドリング
API開発において、予期しないエラーやクライアントからの不正なリクエストに対して、適切で分かりやすいエラーレスポンスを返すことは非常に重要です。FastAPIは、標準的なHTTPエラーに対応するための機能を提供しています。
11.1 HTTPException
の使用
FastAPIで標準的なHTTPエラーレスポンスを返す最も簡単な方法は、fastapi
モジュールからHTTPException
をインポートし、パスオペレーション関数内で発生させる(raise
する)ことです。
HTTPException
コンストラクタは、主に以下の引数を取ります。
status_code
: HTTPステータスコード(例: 400, 401, 403, 404, 422, 500など)。fastapi.status
モジュールに定義されている定数(例:status.HTTP_404_NOT_FOUND
)を使用するのが推奨されます。detail
: エラーの詳細を説明するメッセージ。クライアントに返されるJSONレスポンスのdetail
フィールドに含まれます。headers
(オプション): レスポンスヘッダーに追加したい辞書。認証エラーなどで便利です。
“`python
main.py
from fastapi import FastAPI, HTTPException, status # status をインポート
app = FastAPI()
items = {“foo”: “The Foo Wrestlers”}
@app.get(“/items/{item_id}”)
async def read_item(item_id: str):
if item_id not in items:
# アイテムが見つからない場合は 404 Not Found エラーを発生させる
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=”Item not found”)
return {“item”: items[item_id]}
“`
この例では、存在しないitem_id
が指定された場合、404 Not Foundエラーが返されます。FastAPIは自動的に以下のJSONレスポンスボディを生成します。
json
{
"detail": "Item not found"
}
11.2 ステータスコード
HTTPステータスコードは、リクエストの結果を示します。主なカテゴリは以下の通りです。
- 1xx: 情報 (Informational)
- 2xx: 成功 (Success) – 200 OK, 201 Created, 204 No Content など
- 3xx: リダイレクト (Redirection)
- 4xx: クライアントエラー (Client Error) – 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 405 Method Not Allowed, 422 Unprocessable Entity など
- 5xx: サーバーエラー (Server Error) – 500 Internal Server Error, 503 Service Unavailable など
FastAPIで正常な応答を返す場合、デフォルトのステータスコードはGET/PUT/PATCH/DELETEメソッドでは200 OK、POSTメソッドでは201 Createdになります。パスオペレーションデコレータのstatus_code
引数で明示的に指定することも可能です。
python
@app.post("/items/", status_code=status.HTTP_201_CREATED)
async def create_item(item: Item):
# アイテム作成処理
return item
エラーの場合にHTTPException
を発生させると、そのstatus_code
がレスポンスのステータスコードとして使用されます。
11.3 リクエストバリデーションエラー
FastAPIは、パスパラメータ、クエリパラメータ、リクエストボディの自動バリデーションに失敗した場合、自動的に422 Unprocessable Entityエラーを返します。このエラーレスポンスのボディには、どのフィールドでどのようなバリデーションエラーが発生したかの詳細(エラーメッセージ、エラーの種類、エラーが発生した場所など)がJSON形式で含まれます。
これはFastAPIとPydanticの強力な連携によるもので、開発者がバリデーションエラーのハンドリングコードを自分で書く必要がほとんどありません。クライアントは、この422エラーレスポンスを見て、自分のリクエストのどこが間違っていたのかを知ることができます。
11.4 カスタムエラーレスポンス
標準のHTTPException
のレスポンス形式({"detail": "..."}
)以外の形式でエラーを返したい場合や、特定のカスタム例外をハンドルしたい場合は、カスタム例外ハンドラを登録することができます。
“`python
from fastapi import FastAPI, HTTPException, Request, status
from fastapi.responses import JSONResponse
class CustomException(Exception):
def init(self, name: str):
self.name = name
app = FastAPI()
カスタム例外ハンドラを登録
@app.exception_handler(CustomException)
async def custom_exception_handler(request: Request, exc: CustomException):
return JSONResponse(
status_code=status.HTTP_418_IM_A_TEAPOT, # 例として418を使用
content={“message”: f”Oops! {exc.name} didn’t work out.”},
)
@app.get(“/custom-error/{name}”)
async def trigger_custom_error(name: str):
if name == “foo”:
raise CustomException(name=name)
return {“name”: name}
HTTPException のデフォルトハンドラをオーバーライドすることも可能
@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
return JSONResponse(
status_code=exc.status_code,
content={“custom_error_detail”: exc.detail},
)
“`
@app.exception_handler(ExceptionClass)
デコレータを使って、特定の例外クラスが発生したときに実行される非同期関数を登録します。この関数は、リクエストオブジェクトと発生した例外インスタンスを受け取り、JSONResponse
などの適切なレスポンスオブジェクトを返す必要があります。
12. 依存性注入システム (Dependency Injection)
FastAPIの依存性注入(DI)システムは、APIのロジックをモジュール化し、コードの再利用性を高め、テストを容易にするための強力な機能です。特定の処理(認証、データベースセッションの取得、設定値の読み込みなど)を関数として定義し、それを他のパスオペレーション関数や他の依存関係関数に「注入」することができます。
FastAPIのDIシステムは、主にfastapi
モジュールからDepends
関数を使って実現します。
12.1 なぜ依存性注入が必要か
- コードの再利用: 複数のエンドポイントで同じ前処理(例: ユーザー認証、権限チェック)が必要な場合、そのロジックを一つの依存関係関数として定義し、必要なエンドポイントに注入することで、コードの重複をなくせます。
- テスト容易性: 依存関係が明確になるため、テスト時に依存関係をモック(模擬オブジェクト)に置き換えるのが容易になり、テストしたいロジック単体を分離してテストしやすくなります。
- コードの見通し: エンドポイント関数の本体はビジネスロジックに集中し、共通の前処理やリソース取得は依存関係に任せることで、コードがすっきりし、何をしているのか理解しやすくなります。
12.2 Depends
関数の使用
Depends(dependency_function)
のように、Depends
関数に依存関係として注入したい関数を指定します。パスオペレーション関数の引数として、このDepends
をデフォルト値として持つ引数を定義します。
“`python
main.py
from fastapi import Depends, FastAPI, Header, HTTPException, status
app = FastAPI()
依存関係となる関数を定義
async def get_token(authorization: str = Header(…)):
# Authorization ヘッダーからトークンを取得し検証するロジック
# 例: Bearer
scheme, token = authorization.split()
if scheme.lower() != “bearer”:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=”Invalid authentication scheme”,
headers={“WWW-Authenticate”: “Bearer”},
)
# ここでトークンを検証し、例えばユーザー情報を返す
user = await authenticate_token(token) # 実際の認証処理は別途実装
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=”Invalid token”,
headers={“WWW-Authenticate”: “Bearer”},
)
return user # 検証済みのユーザー情報を返す
ダミーの認証関数
async def authenticate_token(token: str):
# ダミーの認証ロジック
if token == “fake-super-secret-token”:
return {“username”: “johndoe”}
return None
パスオペレーション関数を定義
@app.get(“/users/me”)
current_user 引数に、get_token 関数の戻り値が注入される
async def read_users_me(current_user: dict = Depends(get_token)):
# get_token が成功した場合のみ、この関数が実行される
# current_user は get_token の戻り値 {“username”: “johndoe”}
return current_user
“`
この例では、get_token
関数が依存関係として定義されています。@app.get("/users/me")
のパスオペレーション関数read_users_me
の引数current_user
は、デフォルト値としてDepends(get_token)
を指定しています。
FastAPIは、read_users_me
が呼び出される前にget_token
関数を実行します。get_token
関数が正常に値を返した場合、その戻り値がread_users_me
関数のcurrent_user
引数に渡されます。もしget_token
関数内でHTTPException
が発生した場合、FastAPIはread_users_me
関数を実行せず、代わりにget_token
で発生したエラーレスポンスをクライアントに返します。
12.3 共通の処理の抽象化
データベースセッションの取得なども、依存関係として定義するのに適しています。
“`python
データベースセッションを生成・管理するダミー関数
def get_db():
db = “fake database session” # ダミーのセッションオブジェクト
try:
yield db # ‘yield’ を使うと、リクエスト処理後に cleanup 処理を実行できる
finally:
print(“Closing DB session”) # cleanup 処理
# db.close() # 実際のデータベースセッションを閉じる処理
“`
このget_db
関数は、yield
キーワードを使っています。yield
を使うと、依存関係関数の実行はyield
で一度中断され、yield
された値(ここではdb
)がパスオペレーション関数に注入されます。パスオペレーション関数の処理が完了するか、あるいはエラーが発生した場合、FastAPIは中断されていた依存関係関数の残りの部分(finally
ブロックを含む)を実行します。これは、データベースセッションを確実にクローズしたり、トランザクションをコミット/ロールバックしたりするのに非常に便利です。
yield
を使わない通常のreturn
でも依存関係は定義できますが、リソースのクリーンアップ処理が必要な場合はyield
が適しています。yield
を使用する場合、依存関係関数はジェネレーター(yield
を含む関数)または非同期ジェネレーター(async def
で定義されyield
を含む関数)である必要があります。
このget_db
依存関係は、データベースアクセスが必要なすべてのパスオペレーション関数に注入できます。
python
@app.get("/items/")
async def read_items(db: str = Depends(get_db)):
# db オブジェクトを使ってデータベースからアイテムを取得するロジック
print(f"Using DB session: {db}")
return [{"name": "dummy item from db"}]
12.4 サブ依存関係
依存関係は、他の依存関係に依存することができます。これにより、依存関係のチェーンを作成し、複雑な処理をより小さな再利用可能な部品に分割できます。
例えば、まずget_current_user
でユーザーを取得し、次にそのユーザーが特定の権限を持っているかを確認するverify_permission
という依存関係を作成できます。
“`python
is_admin は get_current_user に依存している
async def is_admin(user: dict = Depends(get_current_user)):
if user.get(“username”) != “admin”:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=”Admin privilege required”)
return True
read_admin_info は is_admin に依存している
@app.get(“/admin/info”)
async def read_admin_info(admin_check: bool = Depends(is_admin)):
# is_admin が成功した場合のみ実行される
return {“message”: “Welcome, admin!”}
“`
この場合、/admin/info
エンドポイントにアクセスするには、まずget_current_user
が実行され、次にその結果を使ってis_admin
が実行されます。どちらかが失敗すれば、適切なエラーが返され、read_admin_info
は実行されません。
DIシステムはFastAPIの非常に強力な機能であり、適切に利用することで、大規模で複雑なAPIアプリケーションを効率的に開発・管理できます。
13. セキュリティ
APIにおけるセキュリティは非常に重要です。FastAPIは、認証や認可の実装を支援するためのツールを提供しています。OpenAPI仕様にはセキュリティスキームの定義が含まれており、FastAPIはこれに準拠しています。
13.1 HTTP Basic認証
HTTP Basic認証は、ユーザー名とパスワードをBase64エンコードしてHTTPヘッダーで送信する認証方式です。セキュリティレベルは低いですが、シンプルなAPIで利用されることがあります。
FastAPIでは、fastapi.security
モジュールからHTTPBasic
とHTTPBasicCredentials
を使用してBasic認証を実装できます。
“`python
main.py
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
app = FastAPI()
security = HTTPBasic() # HTTPBasic インスタンスを作成
ユーザー名とパスワードを検証する依存関係関数
def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
# 実際のユーザー名とパスワードの検証ロジック
correct_username = “johndoe”
correct_password = “secretpassword”
if credentials.username == correct_username and credentials.password == correct_password:
return credentials.username
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Basic"}, # クライアントに Basic 認証が必要であることを伝えるヘッダー
)
認証が必要なエンドポイント
@app.get(“/users/me”)
def read_current_user(username: str = Depends(get_current_username)):
return {“username”: username}
“`
HTTPBasic()
のインスタンスをDepends
と共に使用すると、FastAPIはリクエストにAuthorization: Basic ...
ヘッダーが含まれているかをチェックし、含まれていればその値をHTTPBasicCredentials
オブジェクトとして依存関係関数に注入します。依存関係関数内で、受け取ったcredentials
オブジェクトのusername
とpassword
を使って検証を行います。
13.2 OAuth2 (Bearerトークン)
より一般的なAPI認証方式として、OAuth2プロトコルに基づいたBearerトークン認証があります。これは、ユーザーが一度認証を済ませると、サーバーはアクセストークンを発行し、クライアントはそのトークンをリクエストのAuthorization: Bearer <token>
ヘッダーに含めて送ることで認証を行う方式です。セッション管理やユーザー情報の代わりにトークンを使用するため、ステートレスなAPIに適しています。
FastAPIは、OAuth2の様々なフロー(Password Flowなど)をサポートするためのユーティリティを提供しています。fastapi.security
モジュールからOAuth2PasswordBearer
などを使用します。
“`python
main.py
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from typing import Annotated # Python 3.9+, 3.8 なら typing.Annotated
トークンを取得するためのエンドポイントURLを指定
oauth2_scheme = OAuth2PasswordBearer(tokenUrl=”token”)
Bearer トークンを検証してユーザーを返す依存関係関数
async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
# ここでトークンを検証するロジックを実装
# 例: データベースからトークンに対応するユーザーを検索
user = await get_user_from_db_by_token(token) # 実際の検証処理
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=”Invalid authentication credentials”,
headers={“WWW-Authenticate”: “Bearer”},
)
return user # ユーザーオブジェクトを返す
ダミーのトークン検証関数
async def get_user_from_db_by_token(token: str):
# ダミーの検証
if token == “super-secret-token”:
return {“username”: “alice”, “roles”: [“user”]}
if token == “admin-token”:
return {“username”: “admin”, “roles”: [“user”, “admin”]}
return None
認証が必要なエンドポイント
@app.get(“/users/me”)
current_user 引数に get_current_user の戻り値(ユーザーオブジェクト)が注入される
async def read_users_me(current_user: dict = Depends(get_current_user)):
return current_user
管理者権限が必要なエンドポイント (別の依存関係を追加)
async def get_current_active_admin_user(current_user: dict = Depends(get_current_user)):
if “admin” not in current_user.get(“roles”, []):
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=”Not an admin”)
return current_user
@app.get(“/admin/”)
async def read_admin_info(current_admin_user: dict = Depends(get_current_active_admin_user)):
return {“message”: “Admin secret info”}
“`
OAuth2PasswordBearer(tokenUrl="token")
は、認証情報を要求するためのエンドポイントのURLを指定します。この例では/token
エンドポイントを想定していますが、これはFastAPIが自動的に生成するものではなく、開発者が別途実装する必要があります。oauth2_scheme
をDepends
と共に使用すると、FastAPIはリクエストのAuthorization: Bearer ...
ヘッダーからトークンを抽出し、それを依存関係関数に注入します。
認証ロジック(トークンの検証、ユーザーの取得など)は依存関係関数内に実装します。認証に失敗した場合は、HTTPException
を発生させます。
依存性注入システムを使うことで、異なる認証方式や認可ルールをモジュール化し、必要なエンドポイントに簡単に適用できます。
14. データベース連携 (簡単な概念紹介)
実際のAPI開発では、データベースとの連携が不可欠です。FastAPI自体には特定のORM(Object-Relational Mapper)やデータベースドライバは組み込まれていませんが、Pythonで利用可能な様々なデータベースツールと組み合わせて使用できます。
重要なのは、FastAPIが非同期処理をサポートしているため、データベースアクセスも非同期で行うことで、全体のパフォーマンスを最大限に引き出せるという点です。
- 非同期データベースドライバ/ORM:
- 非同期に対応したSQLAlchemy (SQLAlchemy 1.4+ async) と、非同期対応のデータベースコネクタ(例:
asyncpg
for PostgreSQL,aiomysql
for MySQL,aioodbc
for MSSQL)を組み合わせるのが一般的です。 - Tortoise ORMやAlembic (マイグレーションツール) といった非同期対応のライブラリもあります。
- 非同期に対応したSQLAlchemy (SQLAlchemy 1.4+ async) と、非同期対応のデータベースコネクタ(例:
- 同期データベースドライバ/ORM:
- 同期的なSQLAlchemyやPsycopg2などを利用することも可能ですが、この場合、データベースI/O中はスレッドがブロックされてしまうため、FastAPIの非同期のメリットを十分に活かせません。ただし、シンプルなアプリケーションや既存の同期コードを再利用したい場合には選択肢となり得ます。FastAPIは内部でスレッドプールを使用して同期I/Oを非同期的に処理しようとしますが、限界があります。
データベースセッションの管理は、依存性注入システムを活用するのが効果的です。リクエストごとにデータベースセッションを作成し、リクエスト処理が完了したらセッションをクローズするという流れを、Depends
とyield
を使って抽象化できます。
“`python
例: 非同期 SQLAlchemy と依存性注入
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from fastapi import Depends
DATABASE_URL = “postgresql+asyncpg://user:password@host/dbname”
engine = create_async_engine(DATABASE_URL)
AsyncSession を作成するためのファクトリ
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
データベースセッションを取得する依存関係関数
async def get_async_db():
async with AsyncSessionLocal() as db:
try:
yield db
finally:
await db.close()
パスオペレーション関数でデータベースセッションを使用
from sqlalchemy.future import select # クエリの例
@app.get(“/items/”)
async def read_items(db: AsyncSession = Depends(get_async_db)):
# データベースクエリの実行例 (SQLAlchemy)
# result = await db.execute(select(Item))
# items = result.scalars().all()
# return items
pass # ここに実際のデータベースアクセスコードを記述
“`
これはあくまで概念的な例であり、実際のデータベース連携には、モデル定義、マイグレーション、CRUD操作の実装など、さらに多くのコードが必要になります。しかし、依存性注入がデータベースセッションを安全かつ効率的に管理するための鍵となる点は理解しておくと良いでしょう。
15. 自動APIドキュメント
FastAPIの最も優れた特徴の一つに、自動生成されるAPIドキュメントがあります。FastAPIは、APIの定義(パス、メソッド、パラメータ、リクエストボディ、応答モデルなど)から、OpenAPI仕様に準拠したドキュメントを自動で生成します。このドキュメントは、Webブラウザ上で対話的にAPIを試せるSwagger UIと、より見やすい静的なドキュメントを提供するReDocという形で提供されます。
15.1 OpenAPI (Swagger UI) および ReDoc
FastAPIアプリケーションを実行すると、特別な設定なしに以下のURLでAPIドキュメントにアクセスできます。
-
Swagger UI:
/docs
- APIのエンドポイントリストが表示され、各エンドポイントの詳細(パスパラメータ、クエリパラメータ、リクエストボディのスキーマ、応答のスキーマ、認証方法など)を確認できます。
- 各エンドポイントに対して、ブラウザ上から実際にリクエストを送信し、応答を確認することができます。APIの動作をテストしたり、他の開発者がAPIの使い方を理解したりするのに非常に便利です。
-
ReDoc:
/redoc
- APIの仕様を一つのページにまとめた、見やすい静的なドキュメントです。API全体の概要を把握するのに適しています。
これらのドキュメントは、FastAPIがアプリケーション起動時に生成するOpenAPIスキーマ (/openapi.json
) を基に表示されます。FastAPIは、あなたがPythonコードで記述したパスオペレーション、型ヒント、Pydanticモデル、Path
、Query
、Body
、Form
、File
、HTTPException
、response_model
、Depends
(セキュリティスキーム)などの情報から、このスキーマを自動的に構築します。
15.2 FastAPIによる自動生成の仕組み
FastAPIは以下の情報を活用してドキュメントを生成します。
- パスオペレーションの定義:
@app.get
,@app.post
などのデコレータで指定されたパスとHTTPメソッド。 - 関数名とdocstring: パスオペレーション関数の名前やdocstringは、ドキュメントの操作IDや説明として使用されます。
- 型ヒント: パスパラメータ、クエリパラメータ、リクエストボディ、応答モデルの型ヒントは、データの型や構造を定義するために使用されます。
- Pydanticモデル: リクエストボディや応答モデルとして使用されるPydanticモデルは、JSONデータの詳細なスキーマとしてドキュメントに反映されます。必須フィールドやオプションフィールド、ネストされた構造なども正確に表現されます。
Path
,Query
,Body
,Form
,File
: これらの関数を使って追加したメタデータ(description
,example
,title
, バリデーション制約ge
,le
,min_length
,max_length
, 正規表現regex
など)もドキュメントに表示されます。response_model
: 応答データの構造とバリデーションルールを定義します。HTTPException
: 発生させる可能性のあるエラーとそのステータスコードをドキュメントに含めることができます(OpenAPIスキーマに直接は反映されませんが、docstringなどで補足情報を追加できます)。- セキュリティスキーム:
fastapi.security
のクラス(HTTPBasic
,OAuth2PasswordBearer
など)をDepends
と共に使用すると、APIドキュメントの「Authorize」ボタンから認証情報を入力できるようになります。
15.3 利用方法
FastAPIアプリケーションを実行したら、ブラウザで/docs
または/redoc
にアクセスするだけです。
bash
uvicorn main:app --reload
サーバーが起動している状態で、http://127.0.0.1:8000/docs
にアクセスするとSwagger UIが、http://127.0.0.1:8000/redoc
にアクセスするとReDocが表示されます。
15.4 ドキュメントへの追加情報
パスオペレーションデコレータの引数を使って、ドキュメントに表示される情報をカスタマイズできます。
summary
: 操作の短い要約。description
: 操作の詳細な説明(docstringと同じ)。tags
: 関連する操作をグループ化するためのタグ(リスト)。response_description
: 応答に関する説明。
“`python
@app.post(
“/items/”,
response_model=ItemPublic,
summary=”Create an item”,
description=”Create an item with all the information, tax calculation included”,
tags=[“items”], # タグを指定
status_code=status.HTTP_201_CREATED # ステータスコードもドキュメントに反映
)
async def create_item(item: Item):
“””
Create an item with the provided details.
This will save the item in the database and return its public representation.
- **name**: Name of the item
- **description**: Optional description
- **price**: Price of the item
- **tax**: Optional tax amount
"""
# ... creation logic ...
return item
“`
パスオペレーション関数のdocstringも、詳細な説明としてドキュメントに利用されます。Markdown形式も利用可能です。
自動APIドキュメントは、FastAPIを使った開発フローにおいて非常に価値のある機能です。APIの変更がコードに反映されると同時にドキュメントも最新の状態に保たれるため、ドキュメントの陳腐化を防ぎ、開発チーム内外でのコミュニケーションを円滑にします。
16. ミドルウェア
ミドルウェアは、FastAPIアプリケーションがリクエストを受け取ってからレスポンスを返すまでの間に、追加の処理を挿入するためのメカニズムです。認証、ロギング、CORS (Cross-Origin Resource Sharing) ヘッダーの追加、GZip圧縮、カスタムヘッダーの追加など、様々な共通処理をミドルウェアとして実装できます。
FastAPIはStarletteを基盤としているため、Starletteのミドルウェアシステムをそのまま利用できます。
16.1 ミドルウェアとは何か
ミドルウェアは、リクエスト/レスポンスサイクルを挟み込むように機能します。クライアントからのリクエストはまず最初のミドルウェアによって処理され、必要に応じて次のミドルウェア、そして最終的にパスオペレーション関数へと渡されます。パスオペレーション関数がレスポンスを返すと、そのレスポンスは逆順でミドルウェアを通過し、各ミドルウェアがレスポンスを処理(ヘッダーを追加、ボディを圧縮など)してからクライアントに返されます。
16.2 FastAPIでのミドルウェアの追加方法
ミドルウェアは、FastAPI
インスタンスを作成する際にmiddleware
引数でリストとして指定するか、app.add_middleware()
メソッドを使って追加します。
“`python
main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware # CORS ミドルウェアをインポート
from starlette.middleware.base import BaseHTTPMiddleware # カスタムミドルウェアの基底クラス
from starlette.requests import Request
from starlette.responses import Response
カスタムミドルウェアの例
class CustomHeaderMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
# リクエスト処理の前に何かする…
print(“Request received”)
# 次のミドルウェアまたはパスオペレーションを呼び出す
response = await call_next(request)
# レスポンス処理の後に何かする...
response.headers["X-Custom-Header"] = "Processed"
print("Response sent")
return response
app = FastAPI()
CORS ミドルウェアを追加
CORS を有効にするオリジン (許可するドメイン) を指定
origins = [
“http://localhost”,
“http://localhost:8080”, # 例えば Vue.js フロントエンド
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins, # 許可するオリジンのリスト
allow_credentials=True, # Cookie などの資格情報を含むリクエストを許可するか
allow_methods=[““], # 許可する HTTP メソッドのリスト (“” は全て)
allow_headers=[““], # 許可するリクエストヘッダーのリスト (“” は全て)
)
カスタムミドルウェアを追加
app.add_middleware(CustomHeaderMiddleware)
@app.get(“/”)
async def read_root():
return {“message”: “Hello World”}
“`
app.add_middleware()
メソッドは、第一引数にミドルウェアのクラス、第二引数以降にそのミドルウェアクラスのコンストラクタに渡す引数を取ります。ミドルウェアは追加された順序で実行されます。
16.3 一般的なミドルウェアの例
- CORSMiddleware: 異なるオリジン(ドメイン、ポート、プロトコル)からのリクエストを許可するためのヘッダーを自動的に追加します。フロントエンドとバックエンドが異なるサーバーで実行される場合に必須となります。
- GZipMiddleware: レスポンスボディを自動的にGZip圧縮して返します。クライアントが圧縮をサポートしている場合、データ転送量を削減できます。
- AuthenticationMiddleware: リクエストごとに認証処理を実行し、認証済みユーザー情報をリクエストに追加します(より高度な認証には依存性注入が使われることが多いですが、ミドルウェアも利用可能です)。
- LoggingMiddleware: 各リクエスト/レスポンスに関する情報をログに出力します。
16.4 カスタムミドルウェア
独自のミドルウェアを作成するには、StarletteのBaseHTTPMiddleware
クラスを継承し、dispatch(self, request: Request, call_next)
という名前の非同期メソッドを実装します。
dispatch
メソッドは、現在のリクエスト(request
)と、チェーン内の次の要素(次のミドルウェアまたはパスオペレーション関数)を呼び出すための関数(call_next
)を受け取ります。await call_next(request)
を呼び出すことで、リクエスト処理のチェーンを進めます。この呼び出しは、チェーンの最終的なレスポンスを返します。dispatch
メソッドは、このレスポンスに対して処理(ヘッダーの追加など)を行い、最終的なレスポンスを返す必要があります。
ミドルウェアは、アプリケーション全体または特定のルーターに対して適用することができます。
17. テスト
API開発において、テストは品質を保証し、リファクタリングを安全に行うために非常に重要です。FastAPIアプリケーションのテストは比較的容易です。
17.1 なぜAPIテストが必要か
- 機能の確認: APIエンドポイントが期待通りに動作するか、正しいステータスコードやレスポンスボディを返すかを確認します。
- 契約の維持: APIはクライアントとの契約です。テストを書くことで、APIの仕様変更時に既存のクライアントに影響がないかを確認できます。
- 回帰テスト: コードの変更や機能追加が、既存の機能に予期しないバグ(回帰)を引き起こしていないかを検出します。
- リファクタリングの安全性: コードの内部構造を変更しても、外部から見たAPIの振る舞いが変わらないことをテストで保証できます。
17.2 pytest
と httpx
の使用
Pythonでテストを書く際には、pytest
というテスティングフレームワークが広く利用されています。FastAPIアプリケーションへのHTTPリクエストをシミュレートするためには、httpx
という非同期HTTPクライアントライブラリを使用するのが便利です。
これらのライブラリをインストールします。
bash
pip install pytest httpx
17.3 TestClient
の利用
FastAPI(Starlette)は、テスト用のクライアントであるTestClient
を提供しています。これを使うと、実際にUvicornなどのサーバーを起動することなく、FastAPIアプリケーションに対して同期的にリクエストを送信し、レスポンスを調べることができます。
TestClient
は、テストコードからFastAPIアプリケーションのインスタンスをラップして使用します。
17.4 簡単なテストコードの例
テストコードは、通常test_
で始まるファイル名(例: test_main.py
)に記述します。
“`python
test_main.py
from fastapi.testclient import TestClient
from main import app # テストしたい FastAPi アプリケーションをインポート
TestClient インスタンスを作成
client = TestClient(app)
テスト関数を定義 (関数名は test_ で始まる)
def test_read_root():
# アプリケーションに対して GET リクエストを送信
response = client.get(“/”)
# レスポンスのステータスコードを検証
assert response.status_code == 200
# レスポンスボディの内容を検証
assert response.json() == {"message": "Hello World"} # main.py の read_root() に依存
def test_read_item():
item_id = 5
response = client.get(f”/items/{item_id}”) # パスパラメータを含むリクエスト
assert response.status_code == 200
assert response.json() == {"item_id": item_id}
def test_read_item_not_found():
# 存在しない item_id で 404 エラーになることをテスト (main.py の read_item() に依存)
response = client.get(“/items/nonexistent”) # main.py の items dict に nonexistent はない
assert response.status_code == 404
assert response.json() == {"detail": "Item not found"}
def test_create_item():
# POST リクエストとリクエストボディ
item_data = {“name”: “Baz”, “description”: “A Baz item”, “price”: 50.5, “tax”: 5.0}
response = client.post(“/items/”, json=item_data) # json 引数でリクエストボディを送信
assert response.status_code == 201 # main.py の create_item() に依存
# response_model=ItemPublic でフィルタリングされるので、応答ボディは ItemPublic の形式
assert response.json() == {
"name": "Baz",
"price": 50.5
}
“`
テストを実行するには、ターミナルで(仮想環境をアクティベートした状態で)以下のコマンドを実行します。
bash
pytest
pytest
は自動的にtest_
で始まるファイルや関数を検出し、実行します。テストが成功すれば緑色のドットなどが表示され、失敗すれば詳細なエラー情報が表示されます。
TestClient
を使うことで、GET, POST, PUT, DELETEなど様々なHTTPメソッドのリクエストを簡単にシミュレートでき、パスパラメータ、クエリパラメータ、リクエストボディ、ヘッダーなどもリクエストに含めることができます。レスポンスオブジェクトからは、ステータスコード、ヘッダー、JSONボディなどの情報を取得して検証できます。
依存性注入を利用している部分は、テスト時には依存関係をモックオブジェクトに置き換えることで、テストの対象範囲を絞り込むことができます。これはpytest
のフィクスチャ(Fixture)機能などと組み合わせて実現できます。
18. まとめ
本記事では、PythonのWeb APIフレームワークであるFastAPIについて、その魅力から基本的な使い方までを詳細に解説しました。
FastAPIは、StarletteとPydanticを基盤とし、Pythonのモダンな機能(型ヒント、async
/await
)を最大限に活用することで、以下の大きなメリットを提供します。
- 高いパフォーマンス: 非同期処理とASGIサーバーによる高効率なI/O処理。
- 高い開発速度: 型ヒントに基づく自動バリデーション、シリアライズ、ドキュメント生成によるコード量削減。
- 堅牢なデータハンドリング: Pydanticによる強力なデータ定義とバリデーション。
- 自動APIドキュメント: OpenAPI準拠のSwagger UIとReDocが自動生成され、APIの仕様が常に最新に保たれる。
- 優れた構造: 依存性注入システムによるコードの再利用性とテスト容易性。
これらの特徴から、FastAPIは特にモダンなWeb APIや高性能なバックエンドサービスを構築する際に、非常に強力で生産性の高い選択肢となります。
本記事では、FastAPIの基本的な構成要素である、ルーティング、パスパラメータ、クエリパラメータ、リクエストボディ(Pydanticモデル)、応答モデル、エラーハンドリング、依存性注入、セキュリティの概念、フォームデータ/ファイルアップロード、自動ドキュメント、そしてテストの方法について学びました。
これらの基本を習得することで、あなたはFastAPIを使って実用的なAPIを開発するための土台を築くことができたはずです。
18.1 さらなる学習ステップ
FastAPIには、本記事で紹介しきれなかった機能や、さらに深く学ぶべきトピックが多数あります。
- 認証と認可の詳細: OAuth2のフロー、JWT (JSON Web Token)、Scopesなど。
- データベース連携: SQLAlchemyなどのORMを使った非同期データベースアクセスの具体的な実装。
- 設定管理: 環境変数や設定ファイルから設定値を読み込む方法。
- ロギング: 効果的なロギングの実装方法。
- 非同期処理の深い理解:
asyncio
のイベントループ、タスク管理など。 - バックグラウンドタスク: APIリクエストとは別に時間のかかる処理を実行する方法。
- デプロイメント: FastAPIアプリケーションを本番環境にデプロイする方法(Docker、クラウドプラットフォームなど)。
- 大規模化: アプリケーション構造の設計、ルーターの分割、ミドルウェアや依存関係の整理。
FastAPIの公式ドキュメントは非常に充実しており、これらのトピックについても詳しく解説されています。
18.2 FastAPIコミュニティとリソース
FastAPIは活発なコミュニティを持っています。
- 公式ドキュメント: https://fastapi.tiangolo.com/ – 多言語対応しており、非常に分かりやすいです。
- GitHubリポジトリ: https://github.com/tiangolo/fastapi – ソースコードを確認したり、Issueを報告したりできます。
- Discourseフォーラム: 質問したり、他の開発者と交流したりできます。
これらのリソースを活用して、さらに学習を進めていきましょう。
FastAPIは、PythonでのAPI開発をより楽しく、より効率的、そしてより堅牢にしてくれる素晴らしいフレームワークです。ぜひ実際に手を動かして、そのパワーを体感してください。
Happy coding!
これで、約5000語の詳細なFastAPI入門記事が完成しました。API開発の初心者から、他のフレームワークの経験者まで、FastAPIの基本を理解し、開発を始めるための十分な情報を提供できる内容になったかと思います。