SqlAlchemy-migrateを使ってみる
SqlAlchemy-migrateを使ってみる
概要
RailsのActiveRecordのMigrationに影響を受けて、SQLAlchemy を使ったプロジェクトのスキーマ管理をできるようにしたもの。
現時点での最新Verは0.8.2みたいです。
Package Index > sqlalchemy-migrate > 0.8.2
使用方法
ライブラリのインストール
$ pip install sqlalchemy
$ pip install sqlalchemy-migrate
これにより"migrate"コマンドが使えるようになる。
$ migrate --help
プロジェクトの作成
※DBは既に存在していることを前提とする。今回はチュートリアルにのっとりSQLiteを使用します。
ちなみに初期Tableはこんな感じで作ってある。
# create_table.py
from sqlalchemy import *
engine = create_engine('sqlite:///test.db', echo=True)
meta = MetaData()
city = Table('city', meta,
Column('city_id', INTEGER, primary_key=True),
Column('city_name', String(32)))
meta.create_all(engine)
まずはプロジェクトを作る。
$ migrate create test_migrate "Test Project"
$ tree
.
└── test_migrate
├── README
├── __init__.py
├── __init__.pyc
├── manage.py
├── migrate.cfg
└── versions
├── __init__.py
└── __init__.pyc
データベースの初期化
$ cd test_migrate/
$ python manage.py version_control sqlite:///test.db .
毎回、データベース情報引数で渡すのはめんどいので登録しておく。
$ migrate manage manage.py --repository=. --url=sqlite:///test.db
DB見るとマイグレーション用のTableができてる。
$ sqlite3 test.db
$ .explain ON
$ .tables
city migrate_version
sqlite> select * from city;
city city_name
---- -------------
1 Los Angels
2 San Francisco
sqlite> select * from migrate_version;
repo repository_pa vers
---- ------------- ----
Test Project . 0
現在のスキーマバージョン。
$ python manage.py db_version
0
登録されているスキーマバージョンの確認。
$ python manage.py version
0
スキーマ変更用のスクリプトの作成
$ python manage.py script "Add country table"
$ cd versions/
001_Add_country_table.py __init__.py __init__.pyc
001_Add_country_table.pyを書き換える。
# 001_Add_country_table.py
from sqlalchemy import *
from migrate import *
meta = MetaData()
country = Table('country', meta,
Column('id', Integer, primary_key=True),
Column('country_name', String(32))
)
def upgrade(migrate_engine):
meta.bind = migrate_engine
country.create()
def downgrade(migrate_engine):
meta.bind = migrate_engine
country.drop()
ちゃんと動くかテストする。
$ python manage.py test
Upgrading...
done
Downgrading...
done
Success
現在のスキーマバージョン、登録されているスキーマバージョンを確認してみる。 versionが1上がってますね。
$ python manage.py db_version
0
$ python manage.py version
1
スキーマを上げる
$ python manage.py upgrade
0 -> 1...
done
バージョンが上がっているか確認。
$ python manage.py db_version
1
sqliteの中身みてみる。countryが追加されてる。
sqlite> .tables city country migrate_version sqlite> .schema country CREATE TABLE country ( id INTEGER NOT NULL, country_name VARCHAR(32), PRIMARY KEY (id) );
ダウングレードしてみる
できてますね。(countoryが消えてる。)
$ python manage.py downgrade 0
1 -> 0...
done
sqlite> .tables
city migrate_version
元に戻してみてもOK。
$ python manage.py upgrade
0 -> 1...
done
sqlite> .tables
city country migrate_version
カラムの追加
countryテーブルにpopulationカラムを追加してみる。 スクリプトが追加されてますね。
$ python manage.py script "Add population column in country table"
$ ls versions/
001_Add_country_table.py __init__.py
001_Add_country_table.pyc __init__.pyc
002_Add_population_column_in_country_table.py
002_Add_population_column_in_country_table.pyを書き換えてみる。
# 002_Add_population_column_in_country_table.py
from sqlalchemy import *
from migrate import *
def upgrade(migrate_engine):
meta = MetaData(bind=migrate_engine)
country = Table('country', meta, autoload=True)
population_col = Column('population', Integer)
population_col.create(country)
def downgrade(migrate_engine):
meta = MetaData(bind=migrate_engine)
country = Table('country', meta, autoload=True)
country.c.population.drop()
テストしてみる。いけそう。
$ python manage.py test
Upgrading...
done
Downgrading...
done
Success
現在のスキーマバージョン、登録されているスキーマバージョンを確認してみる。
$ python manage.py db_version
1
$ python manage.py version
2
アップデートしてみる。populationカラムが追加されてますね。
$ python manage.py upgrade
1 -> 2...
done
sqlite> .schema country
CREATE TABLE country (
id INTEGER NOT NULL,
country_name VARCHAR(32), population INTEGER,
PRIMARY KEY (id)
);
現在のスキーマバージョン、登録されているスキーマバージョンを確認してみる。
$ python manage.py db_version
2
$ python manage.py version
2
複数バージョン間の移動
もちろんver2からver0、ver0からver2とかもできる。
$ python manage.py downgrade 0
2 -> 1...
done
1 -> 0...
done
$ python manage.py upgrade 2
0 -> 1...
done
1 -> 2...
done
まとめ
SqlAlchemy-migrate非常に便利ですね。Flaskとかとも組み合わせて使ってみたい。