Step by Step
1. In configuration file (development.ini). I change sqlalchemy
#sqlalchemy.url = sqlite:///%(here)s/devdata.db
sqlalchemy.first.url = sqlite:///%(here)s/database_1.db
sqlalchemy.second.url = sqlite:///%(here)s/database_2.db
2. In Application Configuration to load the multiple databases. In file ../config/app_cfg.py
# make sure these imports are added to the top from tg.configuration import AppConfig, config from myapp.model import init_model # add this before base_config = class MultiDBAppConfig(AppConfig):
def _setup_sqlalchemy(self, conf):
#def setup_sqlalchemy(self): """Setup SQLAlchemy database engine(s)""" from sqlalchemy import engine_from_config engine1 = engine_from_config(config, 'sqlalchemy.first.') engine2 = engine_from_config(config, 'sqlalchemy.second.') # engine1 should be assigned to sa_engine as well as your first engine's name config['tg.app_globals'].sa_engine = engine1 config['tg.app_globals'].sa_engine_first = engine1 config['tg.app_globals'].sa_engine_second = engine2 # Pass the engines to init_model, to be able to introspect tables init_model(engine1, engine2) #base_config = AppConfig() base_config = MultiDBAppConfig()
In document Turbogears2 it used def setup_sqlalchemy(self): , when server start will error.
change to def _setup_sqlalchemy(self, conf): , server start will not error.
3. Update your model's __init__ to handle multiple Sessions and Metadata. Add maker2, DBSession2, DeclarativeBase2 and metadata2. Change function init_model in file ../model/__init__.py
# after the first maker/DBSession assignment, add a 2nd one maker2 = sessionmaker(autoflush=True, autocommit=False, extension=ZopeTransactionExtension()) DBSession2 = scoped_session(maker2) # after the first DeclarativeBase assignment, add a 2nd one DeclarativeBase2 = declarative_base() # uncomment the metadata2 line and assign it to DeclarativeBase2.metadata metadata2 = DeclarativeBase2.metadata # finally, modify the init_model method to allow both engines to be passed (see previous step) # and assign the sessions and metadata to each engine def init_model(engine1, engine2): """Call me before using any of the tables or classes in the model.""" #DBSession.configure(bind=engine) DBSession.configure(bind=engine1) DBSession2.configure(bind=engine2) metadata.bind = engine1 metadata2.bind = engine2
4. Tell Your Models Which Engine To Use
4.1 use engine1. create file ../model/spam.py . when query data use DBSession for database_1.db.
from sqlalchemy import Table, ForeignKey, Column from sqlalchemy.types import Integer, Unicode, Boolean from myapp.model import DeclarativeBase, DBSession class Spam(DeclarativeBase): __tablename__ = 'spam' def __init__(self, id, variety): self.id = id self.variety = variety id = Column(Integer, autoincrement=True, primary_key=True) variety = Column(Unicode(50), nullable=False)
@classmethod
def selectAll(cls):
return DBSession.query(cls).all();
4.2 use engine2. create file ../model/eggs.py. when query data use DBSession2 for database_2.db.
from sqlalchemy import Table, ForeignKey, Column from sqlalchemy.types import Integer, Unicode, Boolean from myapp.model import DeclarativeBase2, DBSession2 class Eggs(DeclarativeBase2): __tablename__ = 'eggs' def __init__(self, id, pkg_qty): self.id = id self.pkg_qty = pkg_qty id = Column(Integer, autoincrement=True, primary_key=True) pkg_qty = Column(Integer, default=12)
@classmethod
def selectAll(cls):
return DBSession2.query(cls).all();
I read at http://turbogears.readthedocs.io/en/latest/cookbook/multiple-databases.html#change-the-way-your-app-loads-the-database-engines