首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用sqlalchemy-migrate编写alter column name迁移?

如何使用sqlalchemy-migrate编写alter column name迁移?
EN

Stack Overflow用户
提问于 2011-10-05 18:31:46
回答 3查看 18.2K关注 0票数 17

我正在尝试更改列名。第一次尝试是使用以下脚本:

代码语言:javascript
复制
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')

在我的开发数据库(sqlite)上运行migrate.py test是可行的,升级和降级也是如此。但是,当我在Heroku (使用PostgreSQL 8.3 )上将其部署到我的测试环境中时,我在尝试升级时得到一个跟踪。要点是这样的信息:

代码语言:javascript
复制
sqlalchemy.exc.ProgrammingError: (ProgrammingError) column "id" does not exist 

然后,我尝试在upgrade方法中使用users.c.user_id。这在两种环境中都失败了。

代码语言:javascript
复制
AttributeError: user_id

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

代码语言:javascript
复制
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')

已经推荐的做法是将模型复制粘贴到sqlalchemy-migrate脚本。但是这些额外的重复对我来说有点太多了。任何人都知道应该如何做。假设这是一个bug,我想要一些关于如何解决这个问题的建议。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-10-06 18:10:12

事实证明,有一个比我所希望的更干燥的解决方案。自省!如下所示:

代码语言:javascript
复制
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')

就像一种护身符!

票数 18
EN

Stack Overflow用户

发布于 2017-09-28 00:08:06

这个也行得通:

代码语言:javascript
复制
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')
票数 23
EN

Stack Overflow用户

发布于 2011-10-05 23:10:37

我敢打赌,它不能生成任何SQL,因为您的元数据引用混淆了。您似乎在Table类中使用了两个不同的元数据对象,这确实不太好。你只需要一个。元数据跟踪对象的陈旧情况,是否需要发出对象更新、外键约束等的查询,它还需要知道所有的表和关系。

更改为使用单个MetaData对象,并将echo=True传递给sqlalchemy.create_engine调用,它将把正在使用的SQL查询输出到标准输出。尝试以Postgres的相同角色(用户)登录时自己执行该查询。您可能会发现这是一个简单的权限问题。

关于复制粘贴:我认为Django有一个很好的约定,将Table和声明性类放在它们自己的模块中并导入它们。但是,因为您必须将MetaData对象传递给Table工厂,所以这会使问题复杂化。您可以使用单例/全局元数据对象,也可以直接转换为声明性对象。

有一段时间,我选择实现单参数函数,该函数在给定一个元数据的情况下返回Table对象并缓存结果--实际上实现了一个单例模型类。然后我觉得这很愚蠢,转而使用声明式。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7659957

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档