繁体   English   中英

让 SQLAlchemy 在 create_all 上发出 CREATE SCHEMA

[英]Getting SQLAlchemy to issue CREATE SCHEMA on create_all

我有一个带有架构参数的 SqlAlchemy 模型,如下所示:

Base = declarative_base()

class Road(Base):
  __tablename__ = "roads"
  __table_args__ = {'schema': 'my_schema'}
  id = Column(Integer, primary_key=True)

当我使用Base.metadata.create_all(engine)它会正确地发出一个CREATE TABLE前面有架构名称,就像CREATE TABLE my_schema.roads (但 Postgresql 正确地抱怨架构不存在。

我是否缺少让 SqlAlchemy 发出CREATE SCHEMA my_schema的步骤,还是我必须手动调用它?

我已经在我的 db init 脚本上手动完成了,如下所示:

from sqlalchemy.schema import CreateSchema
engine.execute(CreateSchema('my_schema'))

但这似乎没有我预期的那么神奇。

我遇到了同样的问题,并相信发布 DDL 的“最干净”的方式是这样的:

from sqlalchemy import event
from sqlalchemy.schema import CreateSchema

event.listen(Base.metadata, 'before_create', CreateSchema('my_schema'))

这将确保在创建基础元数据中包含的任何内容之前,您已拥有它的架构。 但是,这不会检查模式是否已经存在。

你可以做CreateSchema('my_schema').execute_if(callback_=check_schema)如果你可以打扰编写check_schema回调(“ 控制 DDL 序列” on should_create in docs)。 或者,作为一种简单的方法,只需使用DDL("CREATE SCHEMA IF NOT EXISTS my_schema")代替(对于 Postgres):

from sqlalchemy import DDL

event.listen(Base.metadata, 'before_create', DDL("CREATE SCHEMA IF NOT EXISTS my_schema"))

我编写了一个函数,它根据接受的答案创建声明的模式。 它使用来自每个映射类的__table_args__ dict 的模式值。

from sqlalchemy import event, DDL


# Import or write your mapped classes and configuration here

def init_db():
    for mapper in Base.registry.mappers:
        cls = mapper.class_
        if issubclass(cls, Base):
            table_args = getattr(cls, '__table_args__', None)
            if table_args:
                schema = table_args.get('schema')
                if schema:
                    stmt = f"CREATE SCHEMA IF NOT EXISTS {schema}"
                    event.listen(Base.metadata, 'before_create', DDL(stmt))
    Base.metadata.create_all(bind=engine)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM