Alembic 检测表已经存在,所以它试图再次创建它们

Alembic detecting tables that already exits,so it trying to create them again

我的动画模型table如下:数据库中没有测试列,我想用alembic更新它。

class Animation(Base):
    __tablename__="Animation"
    id=Column(Integer,primary_key=True,index=True,autoincrement=True)
    name=Column(VARCHAR(100))
    description=Column(VARCHAR(100))
    animation=Column(VARCHAR(100))
    created_at=Column(DateTime)
    updated_at=Column(DateTime)
    test=Column(DateTime)

但是 alembic 检测所有现有的 tables 并试图重新创建它们。所以它 returns 当 ı 运行 命令“alembic upgrade head”时出错。它说 table 已经存在。

版本脚本像这样当 ı 运行 自动生成命令时:

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('Animation',
    sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
    sa.Column('name', sa.VARCHAR(length=100), nullable=True),
    sa.Column('description', sa.VARCHAR(length=100), nullable=True),
    sa.Column('animation', sa.VARCHAR(length=100), nullable=True),
    sa.Column('created_at', sa.DateTime(), nullable=True),
    sa.Column('updated_at', sa.DateTime(), nullable=True),
    sa.Column('test', sa.DateTime(), nullable=True),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_Animation_id'), 'Animation', ['id'], unique=False)
    op.create_table('Faq',
    sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
    sa.Column('title', sa.VARCHAR(length=100), nullable=True),
    sa.Column('description', sa.VARCHAR(length=100), nullable=True),
    sa.Column('animation_id', sa.Integer(), nullable=True),
    sa.Column('created_at', sa.DateTime(), nullable=True),
    sa.Column('updated_at', sa.DateTime(), nullable=True),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_Faq_id'), 'Faq', ['id'], unique=False)
    op.create_table('Service',
    sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
    sa.Column('plate', sa.VARCHAR(length=100), nullable=True),
    sa.Column('arrive_city', sa.VARCHAR(length=100), nullable=True),
    sa.Column('arrive_district', sa.VARCHAR(length=100), nullable=True),
    sa.Column('departure_time', sa.Time(), nullable=True),
    sa.Column('created_at', sa.DateTime(), nullable=True),
    sa.Column('updated_at', sa.DateTime(), nullable=True),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_Service_id'), 'Service', ['id'], unique=False)
    op.drop_index('ix_Service_id', table_name='service')
    op.drop_table('service')
    op.drop_index('ix_Animation_id', table_name='animation')
    op.drop_table('animation')
    op.drop_index('ix_Faq_id', table_name='faq')
    op.drop_table('faq')
    # ### end Alembic commands ###


def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('faq',
    sa.Column('id', mysql.INTEGER(display_width=11), autoincrement=True, nullable=False),
    sa.Column('title', mysql.VARCHAR(collation='utf8_turkish_ci', length=100), nullable=True),
    sa.Column('description', mysql.VARCHAR(collation='utf8_turkish_ci', length=100), nullable=True),
    sa.Column('animation_id', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True),
    sa.Column('created_at', mysql.DATETIME(), nullable=True),
    sa.Column('updated_at', mysql.DATETIME(), nullable=True),
    sa.PrimaryKeyConstraint('id'),
    mysql_collate='utf8_turkish_ci',
    mysql_default_charset='utf8',
    mysql_engine='MyISAM'
    )
    op.create_index('ix_Faq_id', 'faq', ['id'], unique=False)
    op.create_table('animation',
    sa.Column('id', mysql.INTEGER(display_width=11), autoincrement=True, nullable=False),
    sa.Column('name', mysql.VARCHAR(collation='utf8_turkish_ci', length=100), nullable=True),
    sa.Column('description', mysql.VARCHAR(collation='utf8_turkish_ci', length=100), nullable=True),
    sa.Column('animation', mysql.VARCHAR(collation='utf8_turkish_ci', length=100), nullable=True),
    sa.Column('created_at', mysql.DATETIME(), nullable=True),
    sa.Column('updated_at', mysql.DATETIME(), nullable=True),
    sa.PrimaryKeyConstraint('id'),
    mysql_collate='utf8_turkish_ci',
    mysql_default_charset='utf8',
    mysql_engine='MyISAM'
    )
    op.create_index('ix_Animation_id', 'animation', ['id'], unique=False)
    op.create_table('service',
    sa.Column('id', mysql.INTEGER(display_width=11), autoincrement=True, nullable=False),
    sa.Column('plate', mysql.VARCHAR(collation='utf8_turkish_ci', length=100), nullable=True),
    sa.Column('arrive_city', mysql.VARCHAR(collation='utf8_turkish_ci', length=100), nullable=True),
    sa.Column('arrive_district', mysql.VARCHAR(collation='utf8_turkish_ci', length=100), nullable=True),
    sa.Column('departure_time', mysql.TIME(), nullable=True),
    sa.Column('created_at', mysql.DATETIME(), nullable=True),
    sa.Column('updated_at', mysql.DATETIME(), nullable=True),
    sa.PrimaryKeyConstraint('id'),
    mysql_collate='utf8_turkish_ci',
    mysql_default_charset='utf8',
    mysql_engine='MyISAM'
    )
    op.create_index('ix_Service_id', 'service', ['id'], unique=False)
    op.drop_index(op.f('ix_Service_id'), table_name='Service')
    op.drop_table('Service')
    op.drop_index(op.f('ix_Faq_id'), table_name='Faq')
    op.drop_table('Faq')
    op.drop_index(op.f('ix_Animation_id'), table_name='Animation')
    op.drop_table('Animation')
    # ### end Alembic commands ###

我是 alembic 的新手,我找不到任何解决方案。

听起来您已经在数据库中创建了 table,并且现在才开始使用 alembic,因为您需要添加一个新列。所以 alembic 假设它需要创建所有 tables.

要解决此问题,您可以:

  • 删除旧的迁移脚本
  • 备份你的数据库(只是预防措施)
  • 在您的数据库中执行 DELETE FROM alembic_version,如果 table 存在
  • 将代码恢复到添加新列之前的状态
  • 生成一个迁移,记下引用(abc123ef 或类似的)
  • alembic stamp <reference>
  • 为新列添加代码
  • 像往常一样生成并运行 alembic 迁移

alembic stamp设置数据库中之前迁移的引用,所以alembic知道从哪里开始。通过生成初始迁移并 stamping 它,我们让 alembic 知道它只需要 运行 新列的迁移。

您可以简单地 运行 alembic stamp head 而不是生成和标记初始迁移,但我还没有对此进行测试。

实际问题在这里:

class Animation(Base):
    __tablename__="Animation"
    id=Column(Integer,primary_key=True,index=True,autoincrement=True)
    name=Column(VARCHAR(100))
    description=Column(VARCHAR(100))
    animation=Column(VARCHAR(100))
    created_at=Column(DateTime)
    updated_at=Column(DateTime)
    test=Column(DateTime)

table 名称必须以小写字母开头。 Alembic 尝试找到以大写字母 A 开头的 table。但在 MySQL table 中,名称以小写字母开头。所以他们不匹配。所以 Alembic 试图重新创建它们。这解决了我的问题。