alembic是SQLAlchemy的作者写的migrate库。
我是在尝试了解SQLAlchemy-migrate时发现这么一个库的。因为SQLAlchemy-migrate项目说明说,如果你是开始一个新项目的话,推荐使用alembic.
(1)首先安装:
yautous-Mac-mini:microblog yautou$ flask/bin/pip install alembic
Downloading/unpacking alembicapp/ config.py config.pyc db_create.py* flask/ run.py* tmp/ virtualenv.py virtualenv.pyc
(2)然后初始化。 yautous-Mac-mini:microblog yautou$ flask/bin/alembic init alembic
Creating directory /Users/yautou/work/python/microblog/alembic...doneyautous-Mac-mini:microblog yautou$
(3)配置SQLAlchemy的url。
vi alembic.ini
sqlalchemy.url = "sqlite:///app.db"
对于sqlite来讲使用相对位置的话以sqlite:///开头,使用绝对位置的话使用sqlite:////开头。
对于其它数据来说url应该是这样的:
sqlalchemy.url = driver://user:pass@localhost/dbname
yautous-Mac-mini:microblog yautou$ flask/bin/alembic revision -m"create user table"
yautous-Mac-mini:microblog yautou$ cat alembic/versions/32650e9fdf67_create_user_table.py """create user table Revision ID: 32650e9fdf67 Revises: None Create Date: 2013-05-01 11:55:33.111931 """ # revision identifiers, used by Alembic. revision = '32650e9fdf67' down_revision = None from alembic import op import sqlalchemy as sa def upgrade(): op.create_table( 'user', sa.Column('id',sa.Integer,primary_key=True), sa.Column('nickname',sa.String(64),nullable=False,unique=True,index=True), sa.Column('email',sa.String(120),index=True,unique=True), sa.Column('role',sa.SmallInteger,default=0), ) def downgrade(): op.drop_table('user') yautous-Mac-mini:microblog yautou$
(5)进行首次迁移
yautous-Mac-mini:microblog yautou$ vi alembic/versions/32650e9fdf67_create_user_table.py yautous-Mac-mini:microblog yautou$ flask/bin/alembic upgrade head INFO [alembic.migration] Context impl SQLiteImpl. INFO [alembic.migration] Will assume non-transactional DDL. INFO [sqlalchemy.engine.base.Engine] PRAGMA table_info("alembic_version") INFO [sqlalchemy.engine.base.Engine] () DEBUG [sqlalchemy.engine.base.Engine] Col ('cid', 'name', 'type', 'notnull', 'dflt_value', 'pk') DEBUG [sqlalchemy.engine.base.Engine] Row (0, u'version_num', u'VARCHAR(32)', 1, None, 0) INFO [sqlalchemy.engine.base.Engine] SELECT alembic_version.version_num FROM alembic_version INFO [sqlalchemy.engine.base.Engine] () DEBUG [sqlalchemy.engine.base.Engine] Col ('version_num',) INFO [alembic.migration] Running upgrade None -> 32650e9fdf67, create user table INFO [sqlalchemy.engine.base.Engine] CREATE TABLE user ( id INTEGER NOT NULL, nickname VARCHAR(64) NOT NULL, email VARCHAR(120), role SMALLINT, PRIMARY KEY (id) ) INFO [sqlalchemy.engine.base.Engine] () INFO [sqlalchemy.engine.base.Engine] COMMIT INFO [sqlalchemy.engine.base.Engine] CREATE UNIQUE INDEX ix_user_nickname ON user (nickname) INFO [sqlalchemy.engine.base.Engine] () INFO [sqlalchemy.engine.base.Engine] COMMIT INFO [sqlalchemy.engine.base.Engine] CREATE UNIQUE INDEX ix_user_email ON user (email) INFO [sqlalchemy.engine.base.Engine] () INFO [sqlalchemy.engine.base.Engine] COMMIT INFO [sqlalchemy.engine.base.Engine] INSERT INTO alembic_version (version_num) VALUES ('32650e9fdf67') INFO [sqlalchemy.engine.base.Engine] () INFO [sqlalchemy.engine.base.Engine] COMMIT yautous-Mac-mini:microblog yautou$
上面的这种做法,是基本的,
我们还可以让它更智能点,根据我们的model的变化来自动生成更新脚本。
这个时候我们只需要修改下alembic/env.py这个文件的配置就可以了。
将
target_metadata = None改为:
from app import db target_metadata = db.metadata值得注意的是。
alembic/env.py这个文件并不能知道我们的app模块的位置。
所以,我们还需要多写一点代码。
import os import sys root = os.path.dirname(__file__) + '/../' print root sys.path.append(root)
此时我们的app/__init__.py文件内容如下:
#-*- coding:utf-8 -*- from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy server = Flask(__name__) server.config.from_object('config') db = SQLAlchemy(server) from app import views,models
app/models.py如下:
#-*- coding:utf-8 -*- from app import db ROLE_USER = 0 ROLE_ADMIN = 1 class User(db.Model): id = db.Column(db.Integer, primary_key=True) nickname = db.Column(db.String(64), index=True, unique=True) email = db.Column(db.String(120), index=True, unique=True) role = db.Column(db.SmallInteger, default=ROLE_USER) posts = db.relationship('Post', backref='author', lazy='dynamic') def __repr__(self): return "<User %r>" % (self.nickname) class Post(db.Model): id = db.Column(db.Integer, primary_key=True) body = db.Column(db.String(140)) timestamp = db.Column(db.DateTime) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) def __repr__(self): return '<Post %r>' % (self.body)
当我们修改了model时,我们运行下:
$ flask/bin/alembic revision -m" comment message "
然后,你可以查看下生成的脚本。看是否还需要手动修改。
然后运行$ flask/bin/alembic upgrade head
数据库就更新了。
注意:alembic目前还不能处理所以的数据库自动检查更新。
例如你将一列改名了。它会认为只是删除后添加了新的列。