FastAPI で RDB のマイグレーションを管理する
はじめに
個人開発で FastAPI を触る機会があり、Python すらほとんど書いたことがなかったので『動かして学ぶ!Python FastAPI開発入門』という書籍を読んでみた。コンパクトによくまとまっていて、FastAPI を使った開発の雰囲気を一通り掴むことができた。
RDB のスキーママイグレーションの管理方法については記載がなかったので調べたところ、 ORM として sqlalchemy を使う場合、マイグレーション管理には alembic というライブラリを使うのが定番らしい。この記事では sqlalchemy と alembic、MySQL の組み合わせで、最低限のマイグレーション管理をする方法を考えてみる。
これ以降『動かして学ぶ!Python FastAPI開発入門』で説明されている実装が一通り終わっていることを前提として書いていく1。各ツールは以下のバージョンで動作確認を行った。
alembic のインストール
pyproject.toml
に alembic
を追加する。
[tool.poetry.dependencies] ... alembic = "1.13.1" ...
続いて次のコマンドを実行して alembic
のパッケージをインストールする。
$ poetry install
alembic の初期設定
以下を実行してマイグレーション用のディレクトリ構成を初期化する(migrations
の名前は任意)。
$ alembic init migrations
以下のディレクトリとファイルが生成される。
./ ├ migrations │ ├ README │ ├ env.py │ ├ script.py.mako │ └ migrations/ ...
続いてアプリケーショに合わせて migrations/env.py
を修正する。
まずはモデル定義ファイルのメタデータを指定する。またモデル定義ファイルも import しておく必要があるらしい。
... from api.db import Base target_metadata = Base.metadata import api.models.task # noqa: F401 ...
次に sqlalchemy.url
を設定する。
... DB_URL = f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}" config.set_main_option("sqlalchemy.url", DB_URL) ...
alebic.init
にも sqlalchemy.url
の設定項目があるが、重複するのでこちらは削除しておく。
マイグレーションの実行
まずはモデルが定義された Python のファイルを編集する。例えば api/models/task.py
で以下のように User
モデルを追加する。
class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True) name = Column(String(1024), nullable=True)
以下のコマンドを実行すると、データベース側のスキーマ情報とモデルの定義を比較されて差分が versions
ディレクトリ以下にマイグレーションファイルとして作成される。
$ alembic revision --autogenerate
今回のようにモデルを新しく追加した場合は、テーブル作成としてマイグレーションファイルが作成される。
... def upgrade() -> None: # ### commands auto generated by Alembic - please adjust! ### op.create_table('users', sa.Column('id', sa.Integer(), nullable=False), sa.Column('name', sa.String(length=1024), nullable=True), sa.PrimaryKeyConstraint('id') ) # ### end Alembic commands ### def downgrade() -> None: # ### commands auto generated by Alembic - please adjust! ### op.drop_table('users') # ### end Alembic commands ### ...
作成されたマイグレーションファイルを適用するには以下のコマンドを実行され、データベースのalembic_version
テーブルに適用されたマイグレーションファイルの ID が追加される。
$ alembic upgrade head
また実際に発行される DDL は --sql
オプションで事前に確認することもできる。
$ alembic upgrade head --sql
おわりに
この記事では alembic を使った MySQL のマイグレーション管理方法について説明した。基本的な流れとしては Python のモデル定義を修正してマイグレーションファイルを自動生成し、それを適用することを繰り返して行けば最低限の管理はできそうなことがわかった。
『動かして学ぶ!Python FastAPI開発入門』 では Cloud Run 上にアプリケーションをデプロイしていたが、その構成に合わせるのであればマイグレーションの実行は Cloud Run Jobs に切り出して実行するのが良さそう2。
- ただし筆者の都合で Chapter 13 は飛ばしているので aiomysql 周りについては実装していない。↩
- Railsコマンドの実行環境をCloud Run Jobsに移行しました の記事が参考になりそう。↩