让SQLAlchemy在create_all上发出CREATE SCHEMA

时间:2012-12-03 05:41:30

标签: python postgresql sqlalchemy

我有一个带有架构参数的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正确地抱怨模式不存在。< / p>

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

3 个答案:

答案 0 :(得分:26)

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

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

但这似乎不像我期待的那么神奇。

答案 1 :(得分:14)

我遇到了同样的问题并且相信发布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回调(“Controlling DDL Sequences”),则可以执行should_create。{p>或者,作为一种简单的方法,只需使用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"))

答案 2 :(得分:1)

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

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)