I'm writing a library to talk to a database using SQLAlchemy. I really like SQLAlchemy's autoload_with=engine
feature, which can be passed to the Table
constructor to grab all of the table's columns without the programmer having to define them explicitly.
Here's the basic approach for a table named "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
However, we have multiple versions of our database (on different hosts) so I need my engine to be passed in as a parameter at runtime. I sort of hate the idea of writing something like this in my module, but I'm blanking on a better approach:
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
And then client code has to do something nasty like this before using any of the SQLAlchemy models:
import custom_db_api
engine = create_engine(...)
custom_db_api.initialize(engine)
Is there a better approach to handling this kind of module-initialization by an outside caller?
Well, you'll have to find some way to pass the engine
variable to your custom_db_api
module. This might be marginally cleaner...
Base = declarative_base()
class Something(Base):
pass
def initialize(engine):
Something.__table__ = Table('something', Base.metadata, autoload_with=engine)
...or if you can infer the correct engine initialization parameter from some 'global', like sys.argv
, you could use something like this...
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
It kinda depends on how you intend to tell the program which DB to use.