如何使用sqlalchemy-migrate编写alter column name migration?

PEZ*_*PEZ 10 python sqlite postgresql heroku sqlalchemy-migrate

我正在尝试更改列名.首次尝试使用此脚本:

meta = MetaData()

users = Table('users', meta,
    Column('id', Integer, primary_key=True),
    Column('name', String(50), unique=True),
    Column('email', String(120), unique=True)
    )

def upgrade(migrate_engine):
    meta.bind = migrate_engine
    users.c.id.alter(name='id')

def downgrade(migrate_engine):
    meta.bind = migrate_engine
    users.c.id.alter(name='user_id')
Run Code Online (Sandbox Code Playgroud)

migrate.py test在我的开发数据库(源码)的作品也是如此升级和降级.但是当它在Heroku(使用PostgreSQL 8.3)上部署到我的测试环境时,我会在尝试升级时得到一个跟踪.要点就是这个消息:

sqlalchemy.exc.ProgrammingError: (ProgrammingError) column "id" does not exist 
Run Code Online (Sandbox Code Playgroud)

然后我尝试users.c.user_id在升级方法中使用.在两种环境中都失败了:

AttributeError: user_id
Run Code Online (Sandbox Code Playgroud)

我现在使用的解决方法是这个脚本:

meta_old = MetaData()
meta_new = MetaData()

users_old = Table('users', meta_old,
    Column('user_id', Integer, primary_key=True),
    Column('name', String(50), unique=True),
    Column('email', String(120), unique=True)
    )

users_new = Table('users', meta_new,
    Column('id', Integer, primary_key=True),
    Column('name', String(50), unique=True),
    Column('email', String(120), unique=True)
    )

def upgrade(migrate_engine):
    meta_old.bind = migrate_engine
    users_old.c.user_id.alter(name='id')

def downgrade(migrate_engine):
    meta_new.bind = migrate_engine
    users_new.c.id.alter(name='user_id')
Run Code Online (Sandbox Code Playgroud)

已经建议将模型复制粘贴到sqlalchemy-migrate脚本.但是这个额外的重复对我来说有点太多了.任何人都知道应该怎么做.假设这是一个错误,我想建议如何干掉一些变通方法.

PEZ*_*PEZ 14

事实证明,这是一个比我希望的更干的解决方案.内省!像这样:

def upgrade(migrate_engine):
    meta = MetaData(bind=migrate_engine)
    users = Table('users', meta, autoload=True)
    users.c.user_id.alter(name='id')

def downgrade(migrate_engine):
    meta = MetaData(bind=migrate_engine)
    users = Table('users', meta, autoload=True)
    users.c.id.alter(name='user_id')
Run Code Online (Sandbox Code Playgroud)

奇迹般有效!

  • 很好,虽然我担心在架构迁移中使用autoload = True.只是展望未来,请记住在降级时反向应用您的更改!如果你不这样做,你(可能)会收到很多错误! (2认同)

Srđ*_*pić 10

这个也有效:

from alembic import op
....
def upgrade(migrate_engine):
    op.alter_column('users', 'user_id', new_column_name='id')

def downgrade(migrate_engine):
    op.alter_column('users', 'id', new_column_name='user_id')
Run Code Online (Sandbox Code Playgroud)

  • 另外,如果你使用MySQL,每个列的alter操作都需要`existing_type`. (5认同)