
SQLModel入門:FastAPI作者が作ったPython ORMで開発効率を上げる実践ガイド
お疲れ様です!IT業界で働くアライグマです!
「SQLAlchemyでモデルを定義して、Pydanticでスキーマを定義して、両方をメンテナンスするのが面倒…」という声をよく聞きます。FastAPIを使ったAPI開発では、データベースモデルとAPIスキーマの二重定義が避けられない課題でした。
この問題を解決するために、FastAPIの作者であるSebastián Ramírez氏が開発したのがSQLModelです。SQLAlchemyとPydanticを統合し、1つのクラス定義でデータベースモデルとAPIスキーマの両方を兼ねられるようになりました。
本記事では、SQLModelの基本的な使い方から、FastAPIとの連携、実際のプロジェクトでの活用パターンまでを解説します。
SQLModelとは何か:SQLAlchemyとPydanticの統合
SQLModelは、SQLAlchemyのORMとPydanticのデータバリデーションを1つのライブラリに統合したPython ORMです。従来のFastAPI開発では、データベースモデル(SQLAlchemy)とAPIスキーマ(Pydantic)を別々に定義する必要がありました。
従来のアプローチの課題
SQLAlchemyとPydanticを併用する場合、同じデータ構造を2回定義することになります。例えば、ユーザー情報を扱う場合、SQLAlchemyのUserモデルとPydanticのUserSchemaを別々に作成し、両者の整合性を手動で維持する必要がありました。
この二重定義は、フィールドの追加・変更時に両方を更新し忘れるリスクを生みます。Effective Python 第3版 ―Pythonプログラムを改良する125項目でも強調されているように、Pythonでは「同じことを繰り返さない(DRY原則)」が重要です。SQLModelはこの原則に沿った解決策を提供します。
SQLModelの設計思想
SQLModelは、SQLAlchemyの強力なクエリ機能とPydanticの型安全なバリデーションを両立させます。1つのクラス定義から、データベーステーブルの作成、SQLクエリの実行、APIリクエスト/レスポンスのバリデーションがすべて可能になります。
FastAPIとの親和性についてはGraphQL導入判断ガイド:REST APIとの使い分けとプロジェクト適性の見極め方でも触れていますが、SQLModelを使うことでREST API開発の生産性が大幅に向上します。

環境構築とインストール
SQLModelを使い始めるための環境構築手順を説明します。Python 3.7以上が必要です。
インストール
pipでインストールできます。FastAPIと組み合わせる場合は、uvicornも一緒にインストールしておきます。
pip install sqlmodel fastapi uvicorn
SQLModelは内部でSQLAlchemyとPydanticを使用しているため、これらも自動的にインストールされます。
対応データベース
SQLModelはSQLAlchemyをベースにしているため、SQLAlchemyがサポートするすべてのデータベースで動作します。PostgreSQL、MySQL、SQLite、Oracle、Microsoft SQL Serverなどが利用可能です。
開発環境ではSQLiteを使い、本番環境ではPostgreSQLを使うというパターンが一般的です。データベースエキスパートへの道 実践的リレーショナルデータベース設計手法で解説されているように、データベース選定はプロジェクトの要件に応じて慎重に行う必要があります。
ローカルLLMを使った開発環境の構築についてはCursorでローカルLLMを使う完全ガイドも参考になります。SQLModelのコード補完もAIエディタとの相性が良いです。

基本的なモデル定義とCRUD操作
SQLModelの基本的な使い方を、ユーザー管理APIを例に説明します。
モデル定義
SQLModelでは、SQLModelクラスを継承してモデルを定義します。table=Trueを指定すると、データベーステーブルとして扱われます。
from sqlmodel import Field, SQLModel
from typing import Optional
from datetime import datetime
class User(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str = Field(index=True)
email: str = Field(unique=True)
created_at: datetime = Field(default_factory=datetime.utcnow)
is_active: bool = Field(default=True)
このクラスは、データベースのusersテーブルに対応すると同時に、Pydanticモデルとしても機能します。
データベース接続とテーブル作成
SQLModelでは、create_engineでデータベースエンジンを作成し、SQLModel.metadata.create_allでテーブルを作成します。
from sqlmodel import create_engine, Session, SQLModel
DATABASE_URL = "sqlite:///./database.db"
engine = create_engine(DATABASE_URL, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
CRUD操作の実装
セッションを使ってCRUD操作を行います。Fluent Python 第2版 ―Pythonicな思考とコーディング手法で解説されているコンテキストマネージャを活用すると、セッション管理がシンプルになります。
from sqlmodel import select
def create_user(name: str, email: str) -> User:
with Session(engine) as session:
user = User(name=name, email=email)
session.add(user)
session.commit()
session.refresh(user)
return user
def get_user_by_email(email: str) -> Optional[User]:
with Session(engine) as session:
statement = select(User).where(User.email == email)
return session.exec(statement).first()
ケーススタディ:SQLAlchemyからの移行
私のチームでは、ECサイトのバックエンドAPI(テーブル数約30、エンドポイント数約80)をSQLAlchemyからSQLModelへ移行しました。
移行前は、SQLAlchemyのモデル定義ファイルが約1,200行、Pydanticのスキーマ定義ファイルが約800行ありました。移行後は、SQLModelのモデル定義ファイル約720行に統合され、コード量が約40%削減されました。
特に効果が大きかったのは、フィールド追加時の作業です。従来は2ファイルを編集していたのが1ファイルで済むようになり、作業時間が半減しています。
Web APIの設計パターンについてはUber CacheFront設計解説も参考になります。

FastAPIとの連携パターン
SQLModelはFastAPIとの連携を前提に設計されています。実際のAPI開発での活用パターンを紹介します。
依存性注入でセッション管理
FastAPIの依存性注入を使って、リクエストごとにセッションを管理します。
from fastapi import FastAPI, Depends, HTTPException
from sqlmodel import Session
app = FastAPI()
def get_session():
with Session(engine) as session:
yield session
@app.post("/users/", response_model=User)
def create_user_endpoint(user: User, session: Session = Depends(get_session)):
session.add(user)
session.commit()
session.refresh(user)
return user
@app.get("/users/{user_id}", response_model=User)
def read_user(user_id: int, session: Session = Depends(get_session)):
user = session.get(User, user_id)
if not user:
raise HTTPException(status_code=404, detail="User not found")
return user
リクエスト/レスポンス用のサブモデル
実際のAPIでは、作成時と取得時で異なるフィールドを扱うことがあります。SQLModelでは、table=Trueを指定しないサブモデルを定義して対応します。
class UserCreate(SQLModel):
name: str
email: str
class UserRead(SQLModel):
id: int
name: str
email: str
created_at: datetime
is_active: bool
class User(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str = Field(index=True)
email: str = Field(unique=True)
created_at: datetime = Field(default_factory=datetime.utcnow)
is_active: bool = Field(default=True)
Web APIの設計 (Programmer's SELECTION)で解説されているように、APIの入出力を明確に分離することで、セキュリティとメンテナンス性が向上します。
リレーションシップの定義
SQLModelでは、Relationshipを使ってテーブル間のリレーションを定義できます。
from sqlmodel import Relationship
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
members: list["User"] = Relationship(back_populates="team")
class User(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
team_id: Optional[int] = Field(default=None, foreign_key="team.id")
team: Optional[Team] = Relationship(back_populates="members")
AIエージェントを活用した開発効率化についてはOpenAI GPT-5.2の新機能解説も参考になります。

実践的なTipsとハマりポイント
SQLModelを実際のプロジェクトで使う際のTipsと、よくあるハマりポイントを紹介します。
マイグレーション管理
SQLModelには組み込みのマイグレーション機能がありません。本番環境では、Alembicを使ってマイグレーションを管理することを推奨します。
pip install alembic
alembic init migrations
alembic/env.pyでSQLModelのメタデータを参照するように設定します。
N+1問題への対処
リレーションを持つモデルを取得する際、N+1問題が発生しやすいです。selectinloadを使って一括取得することで解決できます。
from sqlalchemy.orm import selectinload
statement = select(Team).options(selectinload(Team.members))
teams = session.exec(statement).all()
型ヒントの活用
SQLModelはPydanticベースなので、型ヒントが厳密に機能します。Python Distilled ―プログラミング言語Pythonのエッセンスで解説されているように、型ヒントを活用することでIDEの補完が効き、バグの早期発見につながります。
私のチームでは、SQLModel導入後にランタイムエラーが約30%減少しました。特に、フィールドの型不一致によるエラーが激減しています。
コード品質の改善については循環的複雑度を活用したコード品質改善も参考になります。

まとめ
SQLModelは、FastAPI作者が開発したPython ORMで、SQLAlchemyとPydanticを統合することで開発効率を大幅に向上させます。
短期的には、モデル定義の二重管理から解放され、コード量が削減されます。型安全なバリデーションにより、ランタイムエラーも減少します。
長期的には、FastAPIとの親和性を活かして、保守性の高いAPIを構築できます。Alembicと組み合わせることで、本番環境でのマイグレーション管理も問題なく行えます。
まずは小さなプロジェクトでSQLModelを試し、従来のSQLAlchemy+Pydanticの構成と比較してみてください。DRY原則に沿ったコードベースの快適さを実感できるはずです。










