python

alembic マイグレーションファイルの作成方法

alembicマイグレーションサムネ画像

Pythonのalembicを使って、マイグレーションファイルを作成することがあったので、メモとして残しておきます。

環境

今回の環境

  • Python 3.9.2
  • alembic 1.7.7
  • SQLAlchemy 1.4.36

pythonはインストール済前提で進めていきます。

alembic、SQLAlchemyは以下のコマンドでインストールできます。

pip install alembic
pip install SQLAlchemy 

まずは、alembic init でalembicのプロジェクトを生成します。

そこから生成されるenv.pyファイルや、SQLAlchemyの設定ファイルを設定する必要がありますが、ここでは説明しません。

あくまで、マイグレーションファイルを生成して、それをDBに反映するところを説明していきます。

SQLAlchemyのモデルを作成する

まずはSQLAlchemyを使って、DBのモデルを作成していきます。

from sqlalchemy import Column, Integer, String

from db_setting import Base

class GamesModel(Base):
    __tablename__ = "games"

    id = Column(Integer, primary_key=True)
    game_name = Column(String(10))
    hardware= Column(String(10));

例として、ゲーム情報を保存する「games」いうテーブルを作成するモデルを作成します。

マイグレーションファイルを自動生成する

以下のコマンドでマイグレーションファイルを生成します。

alembic revision --autogenerate -m "create tables"
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'games'
  Generating /var/www/property_api/data/alembic/versions/20221110_create_new_tables.py ...  done

--autogenerate というオプションを使うと、SQLAlchemyのモデルの内容を元にマイグレーションファイルを自動生成してくれます。

alembic init で生成された versions/ 配下にいかのようなマイグレーションファイルが出来ているはずです。

"""create new tables

Revision ID: fbc25dca372a
Revises: f588cee9fd20
Create Date: 2022-11-10 22:20:29.099543

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'fbc25dca372a'
down_revision = 'f588cee9fd20'
branch_labels = None
depends_on = None


def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('games',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('game_name', sa.String(length=10), nullable=True),
    sa.Column('hardware', sa.String(length=10), nullable=True),
    sa.PrimaryKeyConstraint('id')
    )
    # ### end Alembic commands ###


def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('games')
    # ### end Alembic commands ###

SQLAlchemyのモデルを検知してくれない時がある

テーブルを作成したり、カラムを追加するモデルの場合は、alembic revision --autogenerate コマンドで、モデルの内容を元にマイグレーションファイルを自動生成してくれますが、以下のように既存モデルのカラムの型を変更する場合は、検知してくれません。

from sqlalchemy import Column, Integer, String

from db_setting import Base

class GamesModel(Base):
    __tablename__ = "games"

    id = Column(Integer, primary_key=True)
    game_name = Column(String(10))
  // ↓ 10文字から15文字へ変更しても、検知してくれない!
    hardware= Column(String(15))

ポイント

カラムの型変更の場合は、モデルの内容を元マイグレーションファイルを自動生成してくれない

そのため、自分でマイグレーションファイルを作成する必要があります。

まずは、--autogenerateオプションをつけずに、マイグレーションファイルを生成します。

alembic revision -m "chage_volumn"
  Generating /var/www/property_api/data/alembic/versions/20221110_chage_volumn.py ...  done

そうすると、以下のような中身が空っぽなマイグレーションファイルが生成されます。

"""chage_volumn

Revision ID: 00b62276ab25
Revises: f588cee9fd20
Create Date: 2022-11-10 22:50:54.365593

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '00b62276ab25'
down_revision = 'f588cee9fd20'
branch_labels = None
depends_on = None


def upgrade():
    pass


def downgrade():
    pass

upgradeとdowngradeに以下のように追記します。

先ほどのgamesテーブルのhardwareカラムの型の、String(10)からString(15)に変更します。

def upgrade():
    op.alter_column('games', 'hardware',
               existing_type=mysql.VARCHAR(length=15),
               nullable=False)

def downgrade():
    op.alter_column('games', 'hardware',
               existing_type=mysql.VARCHAR(length=10),
               nullable=False)

upgradeはdbをマイグレーションするときに実行され、downgradeはダウングレード時に実行されます。

DBにマイグレーションファイルを反映する

以下のコマンドでDBにマイグレーションファイルを反映することができます。

alembic upgrade head
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade f588cee9fd20 -> fbc25dca372a, create new tables

以上になります。

-python
-, ,