如何在多个数据库和模式中重用sqlalchemy ORM模型?

2 投票
2 回答
1901 浏览
提问于 2025-04-16 06:11

我有一个SQLAlchemy的ORM模型,目前看起来大概是这样的:

Base = declarative_base()

class Database(Base):

  __tablename__ = "databases"
  __table_args__ = (
    saschema.PrimaryKeyConstraint('db', 'role'),
    {
      'schema' : 'defines',
      },
    )


  db = Column(String, nullable=False)
  role = Column(String, nullable=False)
  server = Column(String)

问题是,这个模型实际上存在于多个数据库中,而且在这些数据库里,它还会存在于多个模式(schema)下。对于任何一个操作,我只会使用一个 (数据库, 模式) 的组合。

现在,我可以通过以下方式设置数据库引擎:

Session = scoped_session(sessionmaker())
Session.configure(bind=my_db_engine)
# ... do my operations on the model here.

但是我不太确定在执行时如何更改 __table_args__,以便让模式是正确的。

2 个回答

1

我也在寻找一个优雅的解决方案来处理这个问题。如果在运行时有标准的表格或模型,但表名、数据库和模式都不同,该怎么处理呢?其他人建议写一个函数,这个函数接受表名和模式作为参数,然后为你构建模型。我发现使用 __abstract__ 是有帮助的。我在这里提出了一个可能有用的解决方案。这个方案涉及到在继承中添加一个具有特定模式/元数据的基础类。

1

一种选择是使用create_engine将模型绑定到一个模式或数据库,而不是直接在实际的数据库中进行绑定。

#first connect to the database that holds the DB and schema
engine1 = create_engine('mysql://user:pass@db.com/schema1')

Session = session(sessionmaker())
session = Session(bind=engine1)

#fetch the first database
database = session.query(Database).first()

engine2 = create_engine('mysql://user:pass@%s/%s' % (database.DB, database.schema))
session2 = Session(bind=engine2)

我不知道这是否是最好的方法,但这确实是一种可行的方式。如果你事先缓存好数据库的列表,那么在大多数情况下,你只需要创建一个会话。

撰写回答