在docker中使用alembic管理数据库的问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huitailang1991/article/details/77334834

alembic是配合SQLAlchemy的一个工具,可以方便的upgrade或downgrade数据库,而不用每次修改都进行reset操作导致数据丢失。

安装和初始化

pip install alembic

安装之后在project的目录下面执行初始化命令:

alembic init APP/NAME

这里APP是我Flask的APP名称,NAME是存放alembic初始化文件的文件夹名称,我这里用的是migrations。

初始化后,进入migrations文件夹,会有versions文件夹,每次生成的revision file会在这儿,env.py环境文件,根据项目设置,以及script.py.mako产生revision file的模板文件,如果需要可以自定义,这里我是将常用的sqlalchemy及时间相关的包导入放在了这里,不用每次都去添加。

在project文件夹下还有一个alembic.ini的文件,也是初始化生成的。

首次使用

docker-compose up # 启动image

假设现在我们要添加一个foo table,执行下面的命令创建一个revision file:

docker-compose exec --user "$(id -d):$(id -g)" website alembic revision -m "create foo table"

其实除开docker的命令,这个和git的使用是很像的,–user “ (idd): (id -g)”这个地方是使用native docker的用户需要的,保证生成的文件归属于用户否则是属于root的,如果是下OSX或Windows下用docker machine可以忽略。

生成的文件在versions文件夹下,文件名为HASH_注释的信息.py,upgrade和downgrade本应为pass,这里我已经手动修改了:

import sqlalchemy as sa

from alembic import op

from lib.util_datetime import tzware_datetime
from lib.util_sqlalchemy import AwareDateTime


"""
create foo table

Revision ID: 934098c9f899
Revises: 
Create Date: 2017-08-16 01:34:43.895131
"""

# Revision identifiers, used by Alembic.
revision = '934098c9f899'
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
    op.create_table('foos',
                    sa.Column('id', sa.Integer, primary_key=True),
                    sa.Column('created_on', AwareDateTime(),
                              default=tzware_datetime),
                    sa.Column('updated_on', AwareDateTime(),
                              default=tzware_datetime,
                              onupdate=tzware_datetime),
                    sa.Column('bar', sa.String(128), index=True))

def downgrade():
    op.drop_table('foos')

手动修改了upgrade和downgrade方法后,就可以去terminal中运行了:

docker-compose exec website alembic upgrade head

这里head始终表示revision的最新文件,即使你多次降级后,执行upgrade head仍然是执行的最新的revision file。

升级成功后,会提示已经指向了这次升级的revision的hash。同理,降级:

docker-compose exec website alembic downgrade -1

降级一次,升级也能用+1,这里也可以用其他数字。

写到这里,大家可能觉得不好用,因为这还没有结合SQLAlchemy来使用。

与SQLAlchemy一起用

加减个新表不是使用alembic的真正价值所在,这次我们需要在users的表中增加一列foobar

首先,我们找到users models.py,在User下直接添加一列foobar,这时再升级就需要使用–autogenerate这个flag了,他能帮我们自动的生成相应的revision file,而不是生成空白的自己去填写,我们需要做的就是检查是否正确,做修改后执行升级操作:

docker-compose exec --user "$(id -u):$(id -g)" website alembic revision --autogenerate -m "add foobar column to users"

这里会生成一个新的revision file,但是你会发现这里有对foo table的操作,比如会在升级的时候drop foo table,因为自动生成是根据ORM的关系来构建的,而foo是我们通过修改revision file生成的,不存在于model中,所以,这里如果要保留foo就应该将其中对foo的操作去掉,去掉后结果如下:

import sqlalchemy as sa

from alembic import op

from lib.util_datetime import tzware_datetime
from lib.util_sqlalchemy import AwareDateTime
from sqlalchemy.dialects import postgresql

"""
add foobar column to users

Revision ID: d7676576f4ef
Revises: 73428a75ef16
Create Date: 2017-08-16 15:16:10.539365
"""

# Revision identifiers, used by Alembic.
revision = 'd7676576f4ef'
down_revision = '73428a75ef16'
branch_labels = None
depends_on = None


def upgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.add_column('users', sa.Column('foobar', sa.String(length=128), nullable=True))
    op.create_index(op.f('ix_users_foobar'), 'users', ['foobar'], unique=False)
    ### end Alembic commands ###


def downgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('ix_users_foobar'), table_name='users')
    op.drop_column('users', 'foobar')
    ### end Alembic commands ###

这时我们再去执行一次升级操作就能完成对users这个表添加foobar列的操作。

补充命令行

docker-compose exec website alembic current # 查询当前所在的revision
docker-compose exec website alembic history --verbose # revision的详细历史记录

其他不清楚的都能用 –help这个flag查询。

猜你喜欢

转载自blog.csdn.net/huitailang1991/article/details/77334834