A manager to easily handle multiple SQLAlchemy configurations
Project description
SQLAlchemy bind manager
This package provides an easy way to configure and use SQLAlchemy engines and sessions without depending on frameworks.
It is composed by two main components:
- A manager class for SQLAlchemy engine and session configuration
- A repository/unit-of-work pattern implementation for model retrieval and persistence
Installation
pip install sqlalchemy-bind-manager
Components maturity
- SQLAlchemy manager: Implementation is mostly finalised, needs testing in production.
- Repository: Implementation is mostly finalised, needs testing in production.
- Unit of work: The implementation is working but limited to repositories using the same engine. Distributed transactions across different engines are not yet supported.
Documentation
The complete documentation can be found here
SQLAlchemy manager
Initialise the manager providing an instance of SQLAlchemyConfig
from sqlalchemy_bind_manager import SQLAlchemyConfig, SQLAlchemyBindManager
config = SQLAlchemyConfig(
engine_url="sqlite:///./sqlite.db",
engine_options=dict(connect_args={"check_same_thread": False}, echo=True),
session_options=dict(expire_on_commit=False),
)
sa_manager = SQLAlchemyBindManager(config)
🚨 NOTE: Using global variables is not thread-safe, please read the Documentation if your application uses multi-threading.
The engine_url
and engine_options
dictionaries accept the same parameters as SQLAlchemy create_engine()
The session_options
dictionary accepts the same parameters as SQLALchemy sessionmaker()
The SQLAlchemyBindManager
provides some helper methods for common operations:
get_bind
: returns aSQLAlchemyBind
orSQLAlchemyAsyncBind
objectget_session
: returns aSession
object, which works also as a context managerget_mapper
: returns the mapper associated with the bind
Example:
bind = sa_manager.get_bind()
class MyModel(bind.declarative_base):
pass
# Persist an object
o = MyModel()
o.name = "John"
with sa_manager.get_session() as session:
session.add(o)
session.commit()
Imperative model declaration is also supported.
Multiple database binds
SQLAlchemyBindManager
accepts also multiple databases configuration, provided as a dictionary. The dictionary keys are used as a reference name for each bind.
from sqlalchemy_bind_manager import SQLAlchemyConfig, SQLAlchemyBindManager
config = {
"default": SQLAlchemyConfig(
engine_url="sqlite:///./sqlite.db",
engine_options=dict(connect_args={"check_same_thread": False}, echo=True),
session_options=dict(expire_on_commit=False),
),
"secondary": SQLAlchemyConfig(
engine_url="sqlite:///./secondary.db",
engine_options=dict(connect_args={"check_same_thread": False}, echo=True),
session_options=dict(expire_on_commit=False),
),
}
sa_manager = SQLAlchemyBindManager(config)
All the SQLAlchemyBindManager
helper methods accept the bind_name
optional parameter:
get_bind(bind_name="default")
: returns aSQLAlchemyBind
orSQLAlchemyAsyncBind
objectget_session(bind_name="default")
: returns aSession
orAsyncSession
object, which works also as a context managerget_mapper(bind_name="default")
: returns the mapper associated with the bind
Asynchronous database binds
Is it possible to supply configurations for asyncio supported engines.
config = SQLAlchemyAsyncConfig(
engine_url="postgresql+asyncpg://scott:tiger@localhost/test",
)
This will make sure we have an AsyncEngine
and an AsyncSession
are initialised, as an asynchronous context manager.
async with sa_manager.get_session() as session:
session.add(o)
await session.commit()
Note that async implementation has several differences from the sync one, make sure to check SQLAlchemy asyncio documentation
Repository / Unit of work
The SQLAlchemyRepository
and SQLAlchemyAsyncRepository
class can be used directly or by extending them.
from sqlalchemy_bind_manager.repository import SQLAlchemyRepository
class MyModel(declarative_base):
pass
# Direct usage
repo_instance = SQLAlchemyRepository(sqlalchemy_bind_manager.get_bind(), model_class=MyModel)
class ModelRepository(SQLAlchemyRepository[MyModel]):
_model = MyModel
def _some_custom_method_implemented(self):
...
# Extended class usage
extended_repo_instance = ModelRepository(sqlalchemy_bind_manager.get_bind())
The repository classes provides methods for common use case:
get
: Retrieve a model by primary keysave
: Persist a modelsave_many
: Persist multiple models in a single transactiondelete
: Delete a modelfind
: Search for a list of models (basically an adapter for SELECT queries)paginated_find
: Search for a list of models, with pagination supportcursor_paginated_find
: Search for a list of models, with cursor based pagination support
Use the Unit Of Work to share a session among multiple repositories
It is possible we need to run several operations in a single database transaction. While a single repository provide by itself an isolated session for single operations, we have to use a different approach for multiple operations.
We can use the UnitOfWork
or the AsyncUnitOfWork
class to provide a shared session to
be used for repository operations, assumed the same bind is used for all the repositories.
class MyRepo(SQLAlchemyRepository):
_model = MyModel
bind = sa_manager.get_bind()
uow = UnitOfWork(bind)
uow.register_repository("repo_a", MyRepo)
uow.register_repository("repo_b", SQLAlchemyRepository, MyOtherModel)
with uow.transaction():
uow.repository("repo_a").save(some_model)
uow.repository("repo_b").save(some_other_model)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file sqlalchemy_bind_manager-0.10.0.tar.gz
.
File metadata
- Download URL: sqlalchemy_bind_manager-0.10.0.tar.gz
- Upload date:
- Size: 18.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.0.0 CPython/3.12.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 94511aef2aed006be8e7ca697527f3ce3c17cb38fb3efed2a0610b1b13632a16 |
|
MD5 | bf787e56ba2e887c47c28a889e722dc2 |
|
BLAKE2b-256 | 89837e6b6853c4e2391fea47c9cfec3720e93c1262c84142bee703407dec1f10 |
File details
Details for the file sqlalchemy_bind_manager-0.10.0-py3-none-any.whl
.
File metadata
- Download URL: sqlalchemy_bind_manager-0.10.0-py3-none-any.whl
- Upload date:
- Size: 30.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.0.0 CPython/3.12.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1d5c596f284be713bb39abc5ca70fdc6e98e681499d4b156b282a1a17c1f631b |
|
MD5 | 2a8d25bb132731d0cd278bdb5ad4cb79 |
|
BLAKE2b-256 | 0f8db799b46f59a5e08cef520068f294b01a65723ac3df463e205818871a60db |