如何在SQLAlchemy列/外键mixin中指定PostgreSQL架构?

时间:2014-11-18 20:34:20

标签: sqlalchemy

现有的PostgreSQL数据库具有以不同“模式”组织的表,以拆分大型数据库(用于在服务器级别扩展和实现微调安全性)。类似地,declarative_base表描述被组织在包中的不同文件中 - 每个模式一个文件:

package
    __init__.py
    tables_in_schema1.py
    tables_in_schema2.py

元数据和引擎对象从包的顶部进入每个文件db.Model。例如, tables_in_schema1.py 将具有(忽略必要的ORM导入,然后需要后向引用)表 alpha

from package import db

class TableAlpha(db.Model, object):
    __tablename__ = "alpha"
    __table_args__ = ({"schema": "schema1"})

    id_alpha = Column(INTEGER, Sequence("pk_alpha", 1, 1), primary_key=True)


class MixinAlphaRelation(object):

    @declared_attr
    def id_alpha(cls):
        return Column(INTEGER, ForeignKey("schema1.alpha.id_alpha"))

现在在 tables_in_schema2.py 中,定义了两个表。一个是独立表,称为 beta ,另一个是 alpha beta 调用表 rho

from package import db
from package.tables_in_schema1 import MixinAlphaRelation

class TableBeta(db.Model, object):
    __tablename__ = "beta"
    __table_args__ = ({"schema": "schema2"})

    id_beta = Column(INTEGER, Sequence("pk_beta", 1, 1), primary_key=True)


class MixinBetaRelation(object):

    @declared_attr
    def id_beta(cls):
        return Column(INTEGER, ForeignKey("schema2.beta.id_beta"))


class TableRho(db.Model, MixinAlphaRelation, MixinBetaRelation):
    __tablename__ = "rho"
    __table_args__ = (
        UniqueConstraint("id_alpha", "id_beta", name="uq_rho_alpha-beta"),
        {"schema": "schema2"})

    id_row = Column(INTEGER, Sequence("pk_rho", 1, 1), primary_key=True)

两个mixins的表 rho 的继承的预期目标是生成一个由三行组成的表(并将mixin重用于其他表,这些表也引用 alpha beta ):

CREATE TABLE schema2.rho (
    id_row INTEGER PRIMARY KEY,
    id_alpha INTEGER REFERENCES schema1.alpha(id_alpha),
    id_beta INTEGER REFERENCES schema2.beta(id_beta)
    );

CREATE INDEX uq_rho_alpha-beta ON schema2.rho(id_alpha, id_beta);

但是,当尝试通过调用db.create_all()重新创建所有这些表时,SQLAlchemy会发出错误:

  

sqlalchemy.exc.NoReferencedTableError:与之关联的外键   列'rho.id_alpha'无法找到表'schema2.alpha'   哪个生成一个外键来定位列'id_alpha'

似乎不是在导入的mixin中指定的 alpha1 位于 schema1 中,SQLAlchemy似乎在 schema2

如何解决这个问题?有没有办法传递/强制mixin的正确架构?感谢。

1 个答案:

答案 0 :(得分:13)

我终于发现了错误 - 表 beta 声明中的拼写错误或额外的下划线:而不是我__tablename__的正确__table_name__。如果未指定__tablename__类成员,SQLAlchemy将使用类名作为表名(默认行为)在服务器上创建表。就我而言,它创建了表 TableBeta 而不是预期的 beta 。这导致外键mixin找不到表。

我采用的方法(在我的问题中详述)是使用mixins和在SQLAlchemy中为用例指定模式的正确方法(不同模式中的表和不同模型文件中的表类声明)。使用通过关键字字典__table_args__传递的{"schema": "schema_name"}类成员在表声明中指定模式名称。模式名称在mixin / column声明中以"schema_name.table_name.column_name"

的形式进行限定