代码之家  ›  专栏  ›  技术社区  ›  moshevi

SqlAlchemy alembic迁移文件不使用中的连接设置环境保护?

  •  2
  • moshevi  · 技术社区  · 8 年前

    我有一个在名为 tenant_schema run_migrations_online 中的函数 env.py 我建立了一个模式图

    我预料到了 sqlalchemy 要将此迁移操作转换为在所需架构上运行,它似乎试图使用该架构运行sql查询 .

    你知道怎么修吗?

    :

    2018-09-05_17-28_247f3546088f_add_foo_column.py

    def upgrade():
        op.add_column('derived_table', sa.Column('foo', sa.BigInteger(), nullable=True), 
                      schema='tenant_schema')
    

    这个 联机运行\u迁移\u 功能:

    schema = 'other_name'  # normally i get the name as an argument from alembic
    def run_migrations_online():
        connectable = create_engine(get_url(), echo=True)
    
        with connectable.connect() as connection:
            # setting up the translation map
            conn = connection.execution_options(schema_translate_map={'tenant_schema': schema})
            context.configure(
                connection=conn,
                target_metadata=target_metadata,
                include_schemas=True,
                version_table_schema=schema,
                include_object=include_object,
            )
            with context.begin_transaction():
                context.run_migrations()
    

    例外情况(完全回溯太长,信息量不大):

    sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) schema "tenant_schema" does not exist
     [SQL: 'ALTER TABLE tenant_schema.derived_table ADD COLUMN foo BIGINT'] 
    (Background on this error at: http://sqlalche.me/e/f405)
    

    ALTER TABLE tenant_schema.derived_table 而不是想要的 ALTER TABLE other_name.derived_table

    1 回复  |  直到 8 年前
        1
  •  1
  •   Mikhail Burshteyn    8 年前

    从 SQLAlchemy docs 关于 schema_translate_map (我的重点):

    由于所有模式都是在alembic迁移操作中直接传递的,因此 架构\翻译\映射 不考虑。

    解决方案

    您可能需要:

    1. os.environ['TENANT_SCHEMA'] 而不是文字字符串 'tenant_schema'

      挂接的正确位置可能是重写呈现函数,请参见中的示例 docs

      或者,您可以尝试注册自定义比较器,该比较器将在alembic之后运行,实际上不会比较任何东西,但将替换 schema alembic生成的具有自定义字符串子类的操作中的属性:

      from alembic.autogenerate import comparators
      
      class FakeSchema(str):
          def __repr__(self):
              return "os.environ['TENANT_SCHEMA']"
      
      @comparators.dispatch_for('schema')
      def tweak_schema(autogen_context, upgrade_ops, schemas):
          for op in upgrade_ops.ops:
              if getattr(op, 'schema', None) == 'tenant_schema':
                  op.schema = FakeSchema(op.schema)
                  autogen_context.imports.add('import os')  # for os.environ
      

      您可以阅读比较器函数 in alembic docs

    2. 将该全局上下文中的架构名称设置为运行迁移时所需的值(在本例中为pass) TENANT_SCHEMA 将环境变量添加到alembic或将其添加到 os.environ 在你的 env.py ).