Base
の代わりに_db.Model
_(Flask-SQLAlchemy)を使用して、Alembicが変更からクラスへの候補の移行を自動生成するのに問題があります。
_env.py
_を変更して、Flaskアプリを作成し、関連するすべてのモデルをインポートし、データベースを初期化してから、移行を実行します。
_...
uri = 'mysql://user:password@Host/dbname?charset=utf8'
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = uri
app.config['SQLALCHEMY_ECHO'] = True
db.init_app(app)
with app.test_request_context():
target_metadata = db.Model.metadata
config.set_main_option('sqlalchemy.url', uri)
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
...
_
このアプローチは、drop_all()
、create_all()
に対しては正常に機能しますが(たとえば、単体テスト用にテストデータベースを再作成する場合)、この場合はフラットになります。自動生成されたバージョンスクリプトには、常に空のアップグレードメソッドとダウングレードメソッドがあります例、
_def upgrade():
### commands auto generated by Alembic - please adjust! ###
pass
### end Alembic commands ###
def downgrade():
### commands auto generated by Alembic - please adjust! ###
pass
### end Alembic commands ###
_
私の変更には、インデックスや外部キーの変更だけでなく、列の名前変更、列定義の変更、etc。が含まれています。
Flask-SQLAlchemyでAlembicを使用している人はいますか?私がどこで間違っているのか考えていますか?
どうもありがとう!
Alembicは、テーブルまたは列の名前変更を自動的に検出できません。デフォルトでは、列タイプの変更も検索されませんが、これに対して_compare_type
_オプションを有効にすることができます。
Alembicドキュメントからの抜粋:
自動生成はデフォルトで以下を検出します。
自動生成は、オプションで以下を検出できます。
EnvironmentContext.configure()
に_compare_type=True
_を設定した場合に発生します。この機能はほとんどの場合うまく機能しますが、デフォルトではオフになっているため、最初にターゲットスキーマでテストできます。ここで呼び出し可能オブジェクトを渡すことによってカスタマイズすることもできます。詳細については、関数のドキュメントを参照してください。EnvironmentContext.configure()
に_compare_server_default=True
_を設定した場合に発生します。この機能は単純なケースではうまく機能しますが、常に正確な結果が得られるとは限りません。 Postgresqlバックエンドは、実際にはデータベースに対して「検出された」値と「メタデータ」値を呼び出して、同等性を判断します。この機能はデフォルトでオフになっているため、最初にターゲットスキーマでテストできます。タイプ比較と同様に、呼び出し可能オブジェクトを渡すことでカスタマイズすることもできます。詳細については、関数のドキュメントを参照してください。自動生成は検出できません:
Enum
を直接サポートしないバックエンドで生成された場合のENUM
などの特別なSQLAlchemyタイプ-これは、サポートされていないデータベースでのそのようなタイプの表現、つまり_CHAR+CHECK
_制約は、任意の種類の_CHAR+CHECK
_である可能性があります。 SQLAlchemyがこれが実際にENUM
であると判断するのは推測にすぎず、一般的には悪い考えです。ここで独自の「推測」関数を実装するには、sqlalchemy.events.DDLEvents.column_reflect()
イベントを使用して特定の列に渡されるSQLAlchemy型を変更し、場合によってはsqlalchemy.events.DDLEvents.after_parent_attach()
を使用して不要なCHECK
制約をインターセプトします。現在、自動生成はできませんが、最終的には以下を検出します。
CHECK
、UNIQUE
、_FOREIGN KEY
_などの独立した制約の追加、削除-これらはまだ実装されていません。現在、新しいテーブル内の制約、既存のテーブルへの「ダウングレード」のPKおよびFK制約、およびSQLAlchemyの「スキーマ」タイプCHECK
で生成されたBoolean
制約を取得します。 Enum
。更新:この最後のリストの一部の項目は、Alembic0.7.xリリースでサポートされています。
私の間違いは、dbがすでに最終状態にある状態で最初の移行を作成しようとしたことでした。これは、既存のバージョンがないことに気づき、モデルに基づいていると考えていました。データベース内のすべてのテーブルを削除するまで空のバージョンを取得しましたが、その後は正常に機能しました。
私もこの問題に直面し、この方法を使用してそれを解決しました:
_migrations/env.py
_ファイルを開き、def run_migrations_online()
関数で_context.configure
_を確認します。_Alembic 1.0.8
_では次のようになります。
_with connectable.connect() as connection:
context.configure(
connection=connection,
target_metadata=target_metadata,
process_revision_directives=process_revision_directives,
**current_app.extensions['migrate'].configure_args,
)
_
The _process_revision_directives=process_revision_directives
_を削除またはコメントしてから、その上に_compare_type=True
_を追加するだけです。
このような:
_with connectable.connect() as connection:
context.configure(
connection=connection,
target_metadata=target_metadata,
# process_revision_directives=process_revision_directives,
**current_app.extensions['migrate'].configure_args,
compare_type=True
)
_
フラスコアレンビックを試してください https://github.com/tobiasandtobias/flask-alembic
昨日やってみました。 drop
操作を除いて、私にとっては問題なく動作します。それらはsqliteでは機能しません( https://bitbucket.org/zzzeek/alembic/issue/21/column-renames-not-supported-on-sqlite )。
私がそれを使用した方法。まず、_python manage.py migrate revision --autogenerate
_を使用してsqliteデータベースに空のテーブルを作成しました。それはそのような移行を生み出すでしょう
_def upgrade():
### commands auto generated by Alembic - please adjust! ###
op.create_table('users_user',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=50), nullable=True),
sa.Column('email', sa.String(length=120), nullable=True),
sa.Column('password', sa.String(length=20), nullable=True),
sa.Column('role', sa.SmallInteger(), nullable=True),
sa.Column('status', sa.SmallInteger(), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email'),
sa.UniqueConstraint('name')
)
### end Alembic commands ###
def downgrade():
### commands auto generated by Alembic - please adjust! ###
op.drop_table('users_user')
### end Alembic commands ###
_
次に-_python manage.py migrate upgrade head
_
次に、新しい列test = db.Column(db.String(20))
をユーザーモデルに追加し、このコマンドを実行しました_python manage.py migrate revision --autogenerate -m 'test field at users'
_
これにより、次のような移行が発生しました。
_def upgrade():
### commands auto generated by Alembic - please adjust! ###
op.add_column('users_user', sa.Column('test', sa.String(length=20), nullable=True))
### end Alembic commands ###
def downgrade():
### commands auto generated by Alembic - please adjust! ###
op.drop_column('users_user', 'test')
### end Alembic commands ###
_
必要な機能がアレムビックでサポートされていないことがわかった場合
テーブル(または列)を削除してから移行する
テーブル(または列)を追加し直してから、再度移行します
これは列挙型の変更でも機能します