Usage¶
To use oslo.db in a project:
Session Handling¶
Session handling is achieved using the oslo_db.sqlalchemy.enginefacade
system. This module presents a function decorator as well as a
context manager approach to delivering Session
as well as
Connection
objects to a function or block.
Both calling styles require the use of a context object. This object may be of any class, though when used with the decorator form, requires special instrumentation.
The context manager form is as follows:
from oslo_db.sqlalchemy import enginefacade
class MyContext(object):
"User-defined context class."
def some_reader_api_function(context):
with enginefacade.reader.using(context) as session:
return session.query(SomeClass).all()
def some_writer_api_function(context, x, y):
with enginefacade.writer.using(context) as session:
session.add(SomeClass(x, y))
def run_some_database_calls():
context = MyContext()
results = some_reader_api_function(context)
some_writer_api_function(context, 5, 10)
The decorator form accesses attributes off the user-defined context
directly; the context must be decorated with the
oslo_db.sqlalchemy.enginefacade.transaction_context_provider()
decorator. Each function must receive the context argument:
from oslo_db.sqlalchemy import enginefacade
@enginefacade.transaction_context_provider
class MyContext(object):
"User-defined context class."
@enginefacade.reader
def some_reader_api_function(context):
return context.session.query(SomeClass).all()
@enginefacade.writer
def some_writer_api_function(context, x, y):
context.session.add(SomeClass(x, y))
def run_some_database_calls():
context = MyContext()
results = some_reader_api_function(context)
some_writer_api_function(context, 5, 10)
connection
modifier can be used when a Session
object is not
needed, e.g. when SQLAlchemy Core
is preferred:
@enginefacade.reader.connection
def _refresh_from_db(context, cache):
sel = sa.select([table.c.id, table.c.name])
res = context.connection.execute(sel).fetchall()
cache.id_cache = {r[1]: r[0] for r in res}
cache.str_cache = {r[0]: r[1] for r in res}
Note
The context.session
and context.connection
attributes
must be accessed within the scope of an appropriate writer/reader block
(either the decorator or contextmanager approach). An AttributeError is
raised otherwise.
The decorator form can also be used with class and instance methods which implicitly receive the first positional argument:
class DatabaseAccessLayer(object):
@classmethod
@enginefacade.reader
def some_reader_api_function(cls, context):
return context.session.query(SomeClass).all()
@enginefacade.writer
def some_writer_api_function(self, context, x, y):
context.session.add(SomeClass(x, y))
Note
Note that enginefacade decorators must be applied before
classmethod, otherwise you will get a TypeError
at import time
(as enginefacade will try to use inspect.getargspec()
on a descriptor,
not on a bound method, please refer to the Data Model section
of the Python Language Reference for details).
The scope of transaction and connectivity for both approaches is managed
transparently. The configuration for the connection comes from the standard
oslo_config.cfg.CONF
collection. Additional configurations can be
established for the enginefacade using the
oslo_db.sqlalchemy.enginefacade.configure()
function, before any use of
the database begins:
from oslo_db.sqlalchemy import enginefacade
enginefacade.configure(
sqlite_fk=True,
max_retries=5,
mysql_sql_mode='ANSI'
)
Base class for models usage¶
from oslo_db.sqlalchemy import models
class ProjectSomething(models.TimestampMixin,
models.ModelBase):
id = Column(Integer, primary_key=True)
...
DB API backend support¶
from oslo_config import cfg
from oslo_db import api as db_api
_BACKEND_MAPPING = {'sqlalchemy': 'project.db.sqlalchemy.api'}
IMPL = db_api.DBAPI.from_config(cfg.CONF, backend_mapping=_BACKEND_MAPPING)
def get_engine():
return IMPL.get_engine()
def get_session():
return IMPL.get_session()
# DB-API method
def do_something(somethind_id):
return IMPL.do_something(somethind_id)
DB migration extensions¶
Available extensions for oslo_db.migration.