将命名约定添加到现有数据库

时间:2014-03-02 15:24:00

标签: python sqlalchemy alembic

我正在使用sqlalchemy,并且正在尝试将alembic集成到数据库迁移中。

我的数据库目前存在,并且定义了许多没有名称的ForeignKeys。我想添加一个命名约定,以允许影响ForeignKey列的迁移。

我已将此处给出的命名约定添加到models.py文件的顶部: SQLAlchemy Naming Constraints

convention = {
      "ix": 'ix_%(column_0_label)s',
      "uq": "uq_%(table_name)s_%(column_0_name)s",
      "ck": "ck_%(table_name)s_%(constraint_name)s",
      "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
      "pk": "pk_%(table_name)s"
              }

DeclarativeBase = declarative_base()


DeclarativeBase.metadata = MetaData(naming_convention=convention)

def db_connect():
   return create_engine(URL(**settings.DATABASE))

def create_reviews_table(engine):
    DeclarativeBase.metadata.create_all(engine)

class Review(DeclarativeBase):

    __tablename__ = 'reviews'

    id = Column(Integer, primary_key=True)
    review_id = Column('review_id', String, primary_key=True)
    resto_id = Column('resto_id', Integer, ForeignKey('restaurants.id'),
            nullable=True)
    url = Column('url', String),
    resto_name = Column('resto_name', String)

我按照教程说明设置了alembic / env.py,将模型的元数据提供给target_metadata。

当我跑步时

$: alembic current

我收到以下错误: sqlalchemy.exc.InvalidRequestError:包含%(constraint_name)标记的命名约定要求明确命名约束。

在文档中,他们说“即使我们只使用Column.unique标志:”1,同样的功能[使用命名约定生成列的名称]也会生效,所以我在想那里应该不是问题(他们继续使用未命名的ForeignKey给出一个例子。)

我是否需要返回并为所有约束提供明确的名称,或者是否有办法自动执行此操作?

4 个答案:

答案 0 :(得分:2)

我知道这个问题很旧,但是我发现没有答案。

此错误消息告诉您的是,您应该显式命名约束。它所指的约束是布尔,枚举等,但不是外键或主键。 因此,遍历表,无论您拥有布尔值还是枚举值,都应在其中添加名称。例如:

is_active = Column(Boolean(name='is_active'))

这就是您需要做的。

答案 1 :(得分:0)

这并非旨在成为明确的答案,也无法回答您的直接技术问题,但它可能是一个“哲学问题”吗?就数据库而言,您的SQLAlchemy代码是真实的来源,或者RDMS是源代码。在这种混合情况面前,两者都有其中的一部分,我会看到两个途径:

  1. 您正在探索的那个:修改数据库的架构以匹配SQLAlchemy模型,并使Python代码成为主代码。这是最直观的,但出于技术和管理方面的原因,可能并非总是可行。

  2. 接受RDMS有SQLAlchemy没有的信息,但幸运的是与日常工作无关。您最好的机会是使用另一个迁移工具(ETL),在迁移数据库之前对数据库进行逆向工程。迁移完成后,您可以将新实例的控制权交还给SQLAlchemy(可能需要对新数据库或模型进行一些调整)。

  3. 没有办法说出哪种方法有效,因为两者都有自己的挑战。但我会考虑第二种方法吗?

答案 2 :(得分:0)

在每个较早的迁移中,我很幸运地将naming_convention改回{},以便它们在正确的历史环境下运行。

仍然完全不确定这可能会产生什么样的有趣副作用。

答案 3 :(得分:0)

只需按照惯例将“ ck”修改为"ck": "ck_%(table_name)s_%(column_0_name)s"。它对我有用。

参阅see sqlalchemy docs