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
以上になります。