FastAPIのファイル構造と設計時の注意点
FastAPIのプロジェクトは、適切なディレクトリ構造を設計することで、可読性や保守性を向上させることができます。本記事では、基本的なファイル構造と、設計時に気を付けるべきポイントについて詳しく解説します。
1. FastAPIの基本的なプロジェクト構造
FastAPIの小規模なプロジェクトであれば main.py
だけで完結できますが、規模が大きくなると適切にディレクトリを分割することが重要になります。以下のような構造が一般的です。
ディレクトリ構造の例
my_fastapi_project/
│── app/
│ │── main.py # アプリケーションのエントリーポイント
│ │── routers/ # ルーティングを分割するためのディレクトリ
│ │ │── __init__.py
│ │ │── user.py # ユーザー関連のAPIルート
│ │ │── item.py # アイテム関連のAPIルート
│ │── models/ # SQLAlchemyなどのモデル定義
│ │ │── __init__.py
│ │ │── user.py
│ │ │── item.py
│ │── schemas/ # Pydanticによるスキーマ定義
│ │ │── __init__.py
│ │ │── user.py
│ │ │── item.py
│ │── database.py # データベース接続設定
│ │── dependencies.py # 依存関係の管理
│ │── config.py # 設定ファイル(環境変数など)
│── tests/ # テスト関連
│ │── test_main.py
│── .env # 環境変数
│── requirements.txt # 必要なパッケージ
│── README.md # プロジェクトの説明
│── Dockerfile # Docker用の設定
2. 各ファイル・ディレクトリの役割
1. main.py
アプリケーションのエントリーポイントとなるファイルです。基本的なFastAPIの起動処理を記述します。
from fastapi import FastAPI
from app.routers import user, item
app = FastAPI()
# ルーターの登録
app.include_router(user.router)
app.include_router(item.router)
@app.get("/")
def read_root():
return {"message": "Welcome to FastAPI!"}
2. routers/
(ルーティングの分割)
APIのエンドポイントを機能ごとに分けることで、コードを整理しやすくなります。
routers/user.py
from fastapi import APIRouter
router = APIRouter()
@router.get("/users/")
def get_users():
return [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]
routers/item.py
from fastapi import APIRouter
router = APIRouter()
@router.get("/items/")
def get_items():
return [{"id": 101, "name": "Item A"}, {"id": 102, "name": "Item B"}]
3. models/
(データベースモデル)
SQLAlchemyを使用する場合、データベースのモデルを定義します。
models/user.py
from sqlalchemy import Column, Integer, String
from app.database import Base
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
4. schemas/
(データのスキーマ)
リクエストやレスポンスのデータ型をPydanticで定義します。
schemas/user.py
from pydantic import BaseModel
class UserSchema(BaseModel):
id: int
name: str
5. database.py
(データベース接続)
データベースとの接続設定を管理します。
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
6. dependencies.py
(依存関係管理)
依存関係を管理し、DI(Dependency Injection)を行うための関数を定義します。
from app.database import SessionLocal
from fastapi import Depends
from sqlalchemy.orm import Session
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
3. 設計時の注意点
1. ルーターは機能ごとに分割
1つのファイルにすべてのAPIエンドポイントを記述すると、管理が困難になります。routers/
を作成し、機能ごとにルーティングを分けるのが理想的です。
2. schemas/
を活用し、リクエスト/レスポンスを統一
Pydanticを使ってリクエストやレスポンスのスキーマを統一すると、データの整合性が保たれ、バリデーションが容易になります。
3. 依存関係は dependencies.py
で管理
依存関係を一元管理することで、テストのしやすさや再利用性が向上します。
4. 環境変数は .env
に分離
データベースの接続情報やAPIキーなどの機密情報は、.env
に保存し、.gitignore
に追加してGit管理から除外します。
.env
DATABASE_URL=postgresql://user:password@localhost/db
config.py
from pydantic import BaseSettings
class Settings(BaseSettings):
database_url: str
class Config:
env_file = ".env"
settings = Settings()
5. tests/
でテストコードを作成
FastAPIのエンドポイントをテストする際には、pytest
を活用すると便利です。
test_main.py
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
def test_read_root():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"message": "Welcome to FastAPI!"}
4. まとめ
- 適切なディレクトリ構造を設計することで、可読性や保守性を向上できる
- ルーティングは
routers/
に分け、機能ごとに整理 - データベースのモデルは
models/
に、スキーマはschemas/
に分離 - 依存関係は
dependencies.py
で管理し、環境変数は.env
に保存 - テストは
tests/
に作成し、品質を維持
このように構成することで、スケールしやすいFastAPIプロジェクトを構築できます!