スキーマのバージョン番号を格納するバージョン テーブルをデータベースに作成し、この番号をアプリケーション内の番号と照合します。
これは、 alembicなどのスキーマ移行ツールで使用されるアプローチと同じです。ここでは、実際の移行ツールを使用して、「create_all()」の代わりに「upgrade」を呼び出すのがベスト プラクティスです。
スキーマの比較は簡単な作業ではありません。alembic には実際にこれを提供する機能が含まれており、API レベルでもアクセスできますが、多くの注意点があり、新しい移行スクリプトを生成するときの時間を節約できます。
編集: Alembic の api: compare_metadata
例:
from alembic.migration import MigrationContext
from alembic.autogenerate import compare_metadata
from sqlalchemy.schema import SchemaItem
from sqlalchemy.types import TypeEngine
from sqlalchemy import (create_engine, MetaData, Column,
Integer, String, Table)
import pprint
engine = create_engine("sqlite://")
engine.execute('''
create table foo (
id integer not null primary key,
old_data varchar,
x integer
)''')
engine.execute('''
create table bar (
data varchar
)''')
metadata = MetaData()
Table('foo', metadata,
Column('id', Integer, primary_key=True),
Column('data', Integer),
Column('x', Integer, nullable=False)
)
Table('bat', metadata,
Column('info', String)
)
mc = MigrationContext.configure(engine.connect())
diff = compare_metadata(mc, metadata)
pprint.pprint(diff, indent=2, width=20)
出力:
[ ( 'add_table',
Table('bat', MetaData(bind=None),
Column('info', String(), table=<bat>), schema=None)),
( 'remove_table',
Table(u'bar', MetaData(bind=None),
Column(u'data', VARCHAR(), table=<bar>), schema=None)),
( 'add_column',
None,
'foo',
Column('data', Integer(), table=<foo>)),
( 'remove_column',
None,
'foo',
Column(u'old_data', VARCHAR(), table=None)),
[ ( 'modify_nullable',
None,
'foo',
u'x',
{ 'existing_server_default': None,
'existing_type': INTEGER()},
True,
False)]]