我有一个名为tenant_schema
的通用模式的迁移。在run_migrations_online
的env.py
函数中,我为tenant_schema
设置了schema_translate_map。
我希望sqlalchemy
能够将这个迁移操作转换为在所需的模式上运行,但是它似乎尝试使用模式tenant_schema
运行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')
run_migrations_online
功能:
env.py
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
来自SQLAlchemy docs关于schema_translate_map
(强调我的):
该特征仅在模式名称直接从表或序列的名称派生的情况下生效;它不会影响直接传递字符串模式名称的方法
由于所有模式都直接在alembic迁移操作中传递,因此不考虑schema_translate_map
。
你可能需要的是:
os.environ['TENANT_SCHEMA']
而不是文字字符串'tenant_schema'
)。
钩子的正确位置可能是覆盖渲染函数,请参阅docs中的示例。不幸的是我无法显示任何代码,因为我自己没有尝试过。
或者,您可以尝试注册自定义比较器,这些比较器将在alembic之后运行,并且实际上不会比较任何内容,但会将alembic生成的操作中的schema
属性替换为自定义字符串子类:
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。TENANT_SCHEMA
环境变量传递给alembic或将其添加到os.environ
中的env.py
中)。