奇怪的Alembic行为

时间:2017-10-30 12:30:38

标签: python database sqlalchemy alembic

我有2个迁移脚本。

脚本1:基础

from models import EntityProperty
from contextlib import contextmanager

# revision identifiers, used by Alembic.
revision = 'ecbde8fa83e3'
down_revision = None
branch_labels = None
depends_on = None

from alembic import op       # noqa
import sqlalchemy as sa      # noqa


@contextmanager
def session_scope():
   session = sa.orm.session.Session(bind=op.get_bind())
   try:
       yield session
       session.commit()
   except:
        session.rollback()
        raise
   finally:
        session.close()


def _upgrade(session):
   properties = session.query(EntityProperty).filter(
      ~EntityProperty._ptype.in_(["AI", "AO", "AV"])
   ).all()

   for _property in properties:
      _property._cov_increment = None


def upgrade():
   with session_scope() as session:
    _upgrade(session)


def downgrade():
    pass

脚本2:

 revision = 'ab47480a7be7'
 down_revision = u'ecbde8fa83e3'
 branch_labels = None
 depends_on = None

 from alembic import op       # noqa
 import sqlalchemy as sa      # noqa


def upgrade():
   # add bacnet_enable to EP
   with op.batch_alter_table(u'entityproperties', schema=None) as batch_op:
      batch_op.execute("PRAGMA foreign_keys=OFF;")
      batch_op.add_column(
          sa.Column(
              'bacnet_object', sa.Boolean(), nullable=True,
              server_default=expression.true()))


 def downgrade():
    with op.batch_alter_table(u'entityproperties', schema=None) as batch_op:
      batch_op.drop_column('bacnet_object')

现在,当我尝试降级到基地时,我收到错误声明

  

没有这样的专栏:entityproperties.bacnet_object

执行基本脚本(脚本1)时会生成此错误。我检查了生成的SQL,它有

  

entityproperties.bacnet_object AS entityproperties_bacnet_object

执行script1时为什么要求bacnet_object列? Script2的降级应该从EntityProperty表中删除该列。我在这里做错了什么?

更新:我在第二个脚本执行后检查了数据库。 EntityProperty表中没有名为bacnet_object的列,但生成的SQL仍然在寻找bacnet_object列?

1 个答案:

答案 0 :(得分:0)

回答我的问题。

当我们从迁移脚本中的应用程序导入模型时,我们可能遇到类似这样的问题。自每次迁移 file表示架构设计的时间点,可能是 与目前的模型非常不同。迁移期间当前模型的这种差异和导入的模型可能会导致问题。

解决方案是在迁移脚本本身中创建表元数据。我们不需要表的所有列,只需要主键和将在迁移脚本中使用的列。在脚本中创建模型后,在更新中我们可以创建会话。这是修饰符脚本1。

"""
"""
from __future__ import unicode_literals
from __future__ import absolute_import

from contextlib import contextmanager
from sqlalchemy.ext.declarative import declarative_base

# revision identifiers, used by Alembic.
revision = 'ecbde8fa83e3'
down_revision = None
branch_labels = None
depends_on = None

from alembic import op       # noqa
import sqlalchemy as sa      # noqa


Base = declarative_base()


class EntityProperty(Base):

    __tablename__ = "entityproperties"
    _uuid = sa.Column(sa.String, primary_key=True, nullable=False)
    _ptype = sa.Column(sa.String, nullable=False)
    _protourl = sa.Column(sa.String)


@contextmanager
def session_scope():
    session = sa.orm.session.Session(bind=op.get_bind())
    try:
        yield session
        session.commit()
    except:
        session.rollback()
        raise
    finally:
        session.close()


def _upgrade(session):
    properties = session.query(EntityProperty).filter(
        ~EntityProperty._ptype.in_(["AI", "AO", "AV"])
    ).all()

    for _property in properties:
        _property._cov_increment = None


def upgrade():
    with session_scope() as session:
        _upgrade(session)


def downgrade():
    pass