1

我正在编写一个库来使用 SQLAlchemy 与数据库通信。我真的很喜欢 SQLAlchemy 的autoload_with=engine特性,它可以传递给Table构造函数来获取表的所有列,而程序员不必显式定义它们。

这是名为“某物”的表的基本方法:

Base = declarative_base()
engine = create_engine('mysql://user:pass@host/db_name')
table = Table('something', Base.metadata, autoload_with=engine)

class Something(Base):
    __table__ = table

但是,我们有多个版本的数据库(在不同的主机上),所以我需要在运行时将我的引擎作为参数传入。我有点讨厌在我的模块中写这样的东西的想法,但我正在寻找更好的方法:

Base = declarative_base()
Something = None   # gets defined after initialize() is called

def initialize(engine):
    table = Table('something', Base.metadata, autoload_with=engine)
    class _Something(Base):
        __table__ = table

    global Something
    Something = _Something

然后在使用任何 SQLAlchemy 模型之前,客户端代码必须做一些像这样令人讨厌的事情:

import custom_db_api

engine = create_engine(...)
custom_db_api.initialize(engine)

有没有更好的方法来处理外部调用者的这种模块初始化?

4

1 回答 1

0

好吧,您必须找到某种方法将engine变量传递给您的custom_db_api模块。这可能稍微干净一些......

Base = declarative_base()

class Something(Base):
    pass

def initialize(engine):
    Something.__table__ = Table('something', Base.metadata, autoload_with=engine)

...或者如果您可以从一些“全局”推断出正确的引擎初始化参数,例如sys.argv,您可以使用类似这样的东西...

import sys

Base = declarative_base()
if len(sys.argv) > 1 and sys.argv[1] == '--use-alt-db':
    engine = create_engine('mysql://user:pass@alt_host/db_name')
else:
    engine = create_engine('mysql://user:pass@main_host/db_name')

table = Table('something', Base.metadata, autoload_with=engine)

class Something(Base):
    __table__ = table

这有点取决于您打算如何告诉程序使用哪个数据库。

于 2013-05-31T18:02:09.203 回答