32

我有一个带有如下模式参数的 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)发出带有架构名称的 a ,但 Postgresql 正确地抱怨架构不存在。CREATE TABLECREATE TABLE my_schema.roads (

我是否错过了让 SqlAlchemy 发出的步骤,CREATE SCHEMA my_schema或者我是否必须手动调用它?

4

3 回答 3

42

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

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

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

于 2012-12-03T05:41:30.347 回答
31

我遇到了同样的问题,并相信发布 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 序列” ),您可以这样做。should_create或者,作为一种简单的方法,只需使用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"))
于 2014-03-06T00:10:32.297 回答
2

我编写了一个函数,它根据接受的答案创建声明的模式。它使用来自每个映射类的__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)
于 2021-03-20T21:04:37.963 回答