我正在编写一个库,使用SQLAlchemy与数据库通信。我非常喜欢SQLAlchemy的autoload_with=engine
功能,可以将其传递给Table
构造函数来获取所有表的列,而无需程序员明确定义它们。
以下是名为“something”的表的基本方法:
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)
外部调用者处理这种模块初始化是否有更好的方法?
答案 0 :(得分: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
这有点取决于您打算如何告诉程序使用哪个DB。