FastAPI + SQLAlchemy + Alembic + SQLiteでマイグレーション
FastAPI + SQLAlchemy + Alembic + SQLiteでマイグレーション FastAPIにはデータベースのマイグレーション機能はありませんが、Alembicというデータベースのマイグレーションツー […]
Filter by Category
FastAPIにはデータベースのマイグレーション機能はありませんが、Alembicというデータベースのマイグレーションツールがあり、マイグレーションファイルを自動で生成できます。本記事ではORMのSQLAlchemyと組み合わせてデータベースのマイグレーションの仕方について解説します。
PC: MacBook Pro (14, 2021)
OS: macOS Monterey 12.6.7
Python: 3.10.0
FastAPI: 0.104.1
Alembic: 1.13.0
SQLAlchemy: 2.0.23
SQLAlchemy-Utils: 0.41.1
.
├── alembic.ini
├── database.py
├── migrations
│ ├── README
│ ├── env.py
│ ├── script.py.mako
│ └── versions
│ ├── 2637abbcf5c1_create_tables.py
│ └── d75d243cebd5_add_age_column.py
├── models
│ ├── mixins.py
│ └── users.py
├── test.db
└── test_main.http
FastAPIは既にインストール済みの状態で、マイグレーションに必要なパッケージのインストールを下記のコマンドで実行します。
pip install alembic SQLAlchemy SQLAlchemy-Utils
Alembic:SQLAlchemyのマイグレーションツール
SQLAlchemy:データベースを操作するORM(Object Relational Mapper)
SQLAlchemy-Utils:SQLAlchemyのユーティリティ関数
下記のコマンドを実行すると、alembic.ini、env.pyなどが入ったmigrationsというディレクトリが生成されます。
alembic init migrations
tree
でディクトリ構造を表示させると下記のようになっています。
.
├── alembic.ini
└── migrations
├── README
├── env.py
├── script.py.mako
└── versions
alembic.ini
...
# the output encoding used when revision files
# are written from script.py.mako
# output_encoding = utf-8
sqlalchemy.url = sqlite:///test.db
[post_write_hooks]
# post_write_hooks defines scripts or Python functions that are run
# on newly generated revision scripts. See the documentation for further
# detail and examples
...
データベースの設定を行うdatabase.pyを作成します。
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, declarative_base
# データベースURL(SQLiteの場合)
SQLALCHEMY_DATABASE_URL = "sqlite:///test.db"
# SQLAlchemy エンジンの作成
engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
# セッションの作成
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
modelsディレクトリにユーザー情報のusers.pyと共通機能のmixins.pyの2つのSQLAlchemyのモデルを作成します。マイグレーションの確認だけであればusers.pyのみで問題ないですが、実際のアプリケーション開発を想定して2つのモデルを用意します。
models/users.py
from sqlalchemy import Column, Integer, String
from sqlalchemy_utils import UUIDType
from uuid import uuid4
from database import Base
from .mixins import TimestampMixin
class User(Base, TimestampMixin):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
uuid = Column(UUIDType(binary=False), nullable=False, default=uuid4)
name = Column(String)
fullname = Column(String)
mixins.pyのTimestampMixinを継承しているので作成日時と更新日時のカラムも作成されます。
models/mixins.py
from sqlalchemy import Column, DateTime, func
class TimestampMixin(object):
created_at = Column(DateTime, default=func.now(), nullable=False, comment="作成日時")
updated_at = Column(DateTime, default=func.now(), onupdate=func.now(), nullable=False, comment="更新日時")
TimestampMixinはusers.pyのUserクラスのように継承させることで作成日時と更新日時のカラムを作成します。
from logging.config import fileConfig
from sqlalchemy import engine_from_config
from sqlalchemy import pool
from alembic import context
# 追記
from database import Base
import models.users # noqa: F401
import models.mixins # noqa: F401
...
# Interpret the config file for Python logging.
# This line sets up loggers basically.
if config.config_file_name is not None:
fileConfig(config.config_file_name)
# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
# 修正
target_metadata = Base.metadata
...
# noqa: F401はエラー対策用に記載
下記のコマンドでcreate tablesという名前のマイグレーションファイルを作成します。
alembic revision --autogenerate -m "create tables"
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.autogenerate.compare] Detected added table 'users'
migrations/versionsにマイグレーションファイル(2637abbcf5c1_create_tables.py)が生成されていれば成功です。
今回はUserクラスのuuidカラムにUUIDを指定しているため、そのままalembic upgrade head
でマイグレーションを実行すると下記のエラーが発生してしまうので予め修正しておきます。(UUIDを使用していない場合はsqlalchemy_utilsのインポートは必要ありません。)
sa.Column('uuid', sqlalchemy_utils.types.uuid.UUIDType(binary=False), nullable=False),
NameError: name 'sqlalchemy_utils' is not defined
2637abbcf5c1_create_tables.py(alembic revision –autogenerate -m “create tables”を実行した際にmigrations/versions内に生成されたマイグレーションファイル)
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
# 追記
import sqlalchemy_utils
...
import sqlalchemy_utils
を追記します。
改めて下記のコマンドでマイグレーションを実行してデータベースに内容を反映します。
alembic upgrade head
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 2637abbcf5c1, create tables
テーブルが追加されました。
エディタのツールやデータベースのアプリなどで画像のようにusersテーブルが確認できればマイグレーション成功です。
users.pyにageカラムを追記してマイグレーションファイルを作成します。
fullname = Column(String)
# 追加
age = Column(Integer)
alembic revision --autogenerate -m "add age column"
migrations/versionsにマイグレーションファイル(d75d243cebd5_add_age_column.py)が生成されていれば成功です。続けて下記のコマンドでマイグレーションを実行します。
alembic upgrade head
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 2637abbcf5c1, create tables
INFO [alembic.runtime.migration] Running upgrade 2637abbcf5c1 -> d75d243cebd5, add age column
画像のようにageカラムが追加されていれば成功です。
データベースを前の状態に戻したいときは下記のコマンドで戻せます。-1で1つ前の状態、-2で2つ前の状態に戻せます。反対に新しい状態にする際は+1、+2で指定できます。
alembic downgrade -1
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.runtime.migration] Running downgrade d75d243cebd5 -> 2637abbcf5c1, add age column
画像のようにageカラムの追加前の状態に戻せていれば成功です。
現在のバージョンを出力
alembic current
出力結果
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
d75d243cebd5 (head)
リビジョンID、元のリビジョンID、作成日などを出力
alembic history --verbose
出力結果
Rev: d75d243cebd5 (head)
Parent: 2637abbcf5c1
Path: /DIRPATH/migrations/versions/d75d243cebd5_add_age_column.py
add age column
Revision ID: d75d243cebd5
Revises: 2637abbcf5c1
Create Date: 2023-12-05 13:37:36.048555
...
データベースの初期化
alembic downgrade base
群馬県でPythonを使ったAIやソフトウェアを開発している株式会社ファントムが運営しています。
メーリングリストに登録するとファントムの最新情報をお届けします
お客様のメールアドレスを共有することはありません