alembic是SQLAlchemy的作者写的migrate库。
我是在尝试了解SQLAlchemy-migrate时发现这么一个库的。因为SQLAlchemy-migrate项目说明说,如果你是开始一个新项目的话,推荐使用alembic.
(1)首先安装:
yautous-Mac-mini:microblog yautou$ flask/bin/pip install alembic
Downloading/unpacking alembicDownloading alembic-0.5.0.tar.gz (387kB): 387kB downloaded
Running setup.py egg_info for package alembic
。。。。。。。
yautous-Mac-mini:microblog yautou$ ls
app/ 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...doneCreating directory /Users/yautou/work/python/microblog/alembic/versions...done
Generating /Users/yautou/work/python/microblog/alembic.ini...done
Generating /Users/yautou/work/python/microblog/alembic/env.py...done
Generating /Users/yautou/work/python/microblog/alembic/env.pyc...done
Generating /Users/yautou/work/python/microblog/alembic/README...done
Generating /Users/yautou/work/python/microblog/alembic/script.py.mako...done
Please edit configuration/connection/logging settings in
'/Users/yautou/work/python/microblog/alembic.ini' before proceeding.
yautous-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目前还不能处理所以的数据库自动检查更新。
例如你将一列改名了。它会认为只是删除后添加了新的列。