2012-08-15 27 views
20

我想修改一些数据库数据作为alembic升级的一部分。修改数据作为alembic升级的一部分

我想我可能只是添加任何代码在我移民的升级,但以下失败:

def upgrade(): 
    ### commands auto generated by Alembic - please adjust! ### 
    op.add_column('smsdelivery', sa.Column('sms_message_part_id', sa.Integer(), sa.ForeignKey('smsmessagepart.id'), nullable=True)) 
    ### end Alembic commands ### 

    from volunteer.models import DBSession, SmsDelivery, SmsMessagePart 

    for sms_delivery in DBSession.query(SmsDelivery).all(): 
     message_part = DBSession.query(SmsMessagePart).filter(SmsMessagePart.message_id == sms_delivery.message_id).first() 
     if message_part is not None: 
      sms_delivery.sms_message_part = message_part 

,出现以下错误:

sqlalchemy.exc.UnboundExecutionError: Could not locate a bind configured on mapper Mapper|SmsDelivery|smsdelivery, SQL expression or this Session 

我没有真正理解这个错误。我该如何解决这个问题,或者正在做这种操作,这不是一种可能性?

+1

如果你解决了这个问题,你可以发布解决方案吗? – Devi 2013-07-09 11:10:01

回答

15

很难理解你正在尝试从代码摘录中获得什么。但我会尝试猜测。所以下面的答案将基于我的猜测。

第4行 - 您从您的模块导入东西(DBSession,SmsDelivery,SmsMessagePart),然后您试图像在应用程序中一样操作这些对象。

错误显示SmsDelivery是一个映射器对象 - 所以它指向某个表。映射器对象应绑定到有效的sqlalchemy连接。

它告诉我跳过DB对象的初始化(连接并将此连接绑定到映射器对象),就像您通常在应用程序代码中执行的操作。

DBSession看起来像SQLAlchemy会话对象 - 它也应该有连接绑定。

Alembic已经具有连接就绪和打开 - 用于通过op。*方法更改要请求的数据库模式。

所以应该有办法得到这个连接。

根据蒸馏器手动op.get_bind()将返回当前连接绑定:
对于充分互动与连接数据库,使用“绑定”,可从上下文:

from alembic import op 
connection = op.get_bind() 

所以,你可以使用这个连接将你的查询运行到db。

PS。我会假设你想对表中的数据进行一些修改。您可以尝试将此修改形成一个更新查询。 Alembic有执行这些更改的特殊方法 - 所以你不需要处理连接。
alembic.operations.Operations.execute

execute(sql, execution_options=None) 

使用当前迁移上下文中执行给定的SQL。

在SQL脚本上下文中,语句直接发送到输出流。但是,没有返回结果,因为此功能旨在生成可在“脱机”模式下运行的更改脚本。

参数:sql - 任何法律SQLAlchemy的表达,包括:

  • 的字符串sqlalchemy.sql.expression.text()构建体。
  • a sqlalchemy.sql.expression。insert()构造。
  • 一个sqlalchemy.sql.expression.update(),
  • sqlalchemy.sql.expression.insert(),或
  • sqlalchemy.sql.expression.delete()构建体。几乎任何东西 这是“可执行的”,如SQL表达式语言教程中所述。
+0

我正在寻找升级现有数据的方法!你的答案应该是被接受的答案。谢谢! – swdev 2013-11-28 00:12:09

0

您还需要进口基地,然后

Base.metatada.bind = op.get_bind() 

并在此之后,你可以用你的模型像往常一样没有错误。

12

其值得注意的是,如果你这样做,你可能要冻结你的ORM模型副本内迁移,就像这样:

class MyType(Base): 
    __tablename__ = 'existing_table' 
    __table_args__ = {'extend_existing': True} 
    id = Column(Integer, ...) 
    .. 

def upgrade(): 
    Base.metadata.bind = op.get_bind() 

    for item in Session.query(MyType).all(): 
    ... 

否则,你就不可避免地结束了在一个情况您orm模型更改和以前的迁移不再起作用

特别注意,要扩展基地,而不是基本类型本身(app.models.MyType),因为你的类型可能会走一些点,并再次,你的迁移将失败。

相关问题