LoginSignup
0
0

More than 1 year has passed since last update.

FastAPIのマイグレーションで、autogenerateしたらtableがdropされる件について

Last updated at Posted at 2023-02-24

概要

alembicでマイグレーションファイル作成する際に行う

alembic revision --autogenerate -m "hogehoge"

このコマンドを実行することで、modelとSQLAlchemyでで定義したmodelの状態とDBの状態との差分を検知して、マイグレーションファイルが自動生成される。

しかし、何回やってもtableがdropされるコードが出来上がる。

def upgrade() -> None:
    op.drop_table('users')
    op.drop_table('posts')


def downgrade() -> None:
    op.create_table('users',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(), nullable=True),
    sa.Column('email', sa.String(), nullable=True),
    )
    op.create_table('posts',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('title', sa.String(), nullable=False),
    sa.Column('content', sa.String(), nullable=True),
    )

ちなみに手書きでコード書いても、add_columnとかはDBに反映されなかった。

解決策

こういったautogenerateが検知されなかったり、

alembic upgrade head

をしてもDBに反映されなかったり、といった原因は往々にして

env.pyの

target_metadata=Base.metadata

にあります。

これはmodelの情報をtarget_metadataに渡すためのコードです。

models.pyが複数あると、Baseクラスのmetadataを結合させる必要が出てくる。

# modelが複数ある場合、importしてくる
from users import models as users_model
from posts import models as posts_model

def combine_metadata(*args):
    m = MetaData()
    for metadata in args:
        for t in metadata.tables.values():
            t.tometadata(m)
    return m

target_metadata = combine_metadata(users_model.Base.metadata, posts_model.Base.metadata)

modelは全てtarget_metadataに入れてあげようねって話でした。

余談

型定義の変更はautogenerateで検知されないらしい。
検知したい時は
compare_type=Trueを追加する

context.configure(
    connection=connection, 
    target_metadata=target_metadata,
    compare_type=True, #同じカラム名でも型の変更を検知する
)

参考

https://qiita.com/orange634nty/items/dcbcc10eb14f5e10f398/
http://liuhongjiang.github.io/hexotech/2015/10/14/alembic-support-multiple-model-files/

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0