| Version 8 (modified by guest, 5 years ago) |
|---|
Working with Multiple Databases
This is a set of simple recipe examples to show how to use Elixir with multiple databases. Tested on SQLAlchemy 0.4 and Elixir 0.4, should work without modification on 0.5.
Single file/program
This example uses entity level setup of binding's between session, metadata and entities with the using_options call to ensure each table is created in it's respective database. Database a.db contains table a and database b.db contains table b. Queries are executed within each using the global Entity name (not shown).
from sqlalchemy.orm import scoped_session, sessionmaker from sqlalchemy import create_engine from sqlalchemy.schema import ThreadLocalMetaData from elixir import * a_engine = create_engine('sqlite:////tmp/a.db', echo=True) a_session = scoped_session(sessionmaker(autoflush=True, transactional=True, bind=a_engine)) a_metadata = metadata a_metadata.bind = a_engine b_engine = create_engine('sqlite:////tmp/b.db', echo=True) b_session = application_session = scoped_session(sessionmaker(autoflush=True, transactional=True, bind=b_engine)) b_metadata = ThreadLocalMetaData() # or just MetaData() for staticengine's (see above posts) b_metadata.bind = b_engine class A(Entity): name = Field(Unicode(30)) using_options(metadata=a_metadata, session=a_session,tablename="a") class B(Entity): name = Field(Unicode(30)) using_options(metadata=b_metadata, session=b_session,tablename="b") create_all() setup_all() adata = A(name="a table data") bdata = B(name="b table data") a_session.commit() b_session.commit()
Multiple files (module)
This version is differentiated by the module level binding's of session, metadata and entity's by setting the __metadata__ and __session__ variables.
a.py
from sqlalchemy.orm import scoped_session, sessionmaker from sqlalchemy import create_engine from elixir import * a_engine = create_engine('sqlite:////tmp/a.db', echo=True) a_session = scoped_session(sessionmaker(autoflush=True, transactional=True)) a_metadata = metadata __metadata__ = a_metadata __session__ = a_session class A(Entity): name = Field(Unicode(30)) using_options(tablename="a")
b.py
from sqlalchemy.orm import scoped_session, sessionmaker from sqlalchemy import create_engine from sqlalchemy.schema import ThreadLocalMetaData from elixir import * b_engine = create_engine('sqlite:////tmp/b.db', echo=True) b_session = scoped_session(sessionmaker(autoflush=True, transactional=True)) b_metadata = ThreadLocalMetaData() __metadata__ = b_metadata __session__ = b_session class B(Entity): name = Field(Unicode(30)) using_options(tablename="b")
This version uses "ThreadLocalMetaData" instead of the well known standard "MetaData", with this type it is possible to rebind multiple times per session. Further explanation of this can be found in the SQLAlchemy Docs.
__init__.py
from a import * from b import * b_metadata.bind = b_engine b_session.bind = b_engine a_metadata.bind = a_engine a_session.bind = a_engine setup_all() create_all() adata = A(name="a table data") bdata = B(name="b table data") a_session.commit() b_session.commit()
This can be imported as a module.
Pylons Integration
Use the "multiple files" method above as a starting point. Remove the "create_engine" lines in the model files a.py and b.py.
project/model/__init__.py
from a import * from b import * setup_all()
development.ini
Just add as many sqlalchemy urls as neccessary.
sqlalchemy.a.url = sqlite:///%(here)s/databases/a.db sqlalchemy.b.url = sqlite:///%(here)s/databases/b.db
project/config/environment.py
Edit the global environment settings and set the following to setup your session's and metadata's when the application is started.
from sqlalchemy import engine_from_config config['pylons.g'].engine_a = engine_from_config(config,'sqlalchemy.a.') config['pylons.g'].engine_b = engine_from_config(config,'sqlalchemy.b.') import project.model as model model.a_session.bind = config['pylons.g'].engine_a model.a_metadata.bind = config['pylons.g'].engine_a model.b_session.bind = config['pylons.g'].engine_b model.b_metadata.bind = config['pylons.g'].engine_b
project/lib/base.py
Edit the end of call method to cleanup with
finally: model.a_session.remove() model.b_session.remove()
