我正在编写一个使用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)
有没有更好的方法来处理这种由外部调用者进行的模块初始化? 嗯,您必须找到一些方法将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
这有点取决于你打算如何告诉程序使用哪个数据库。