https://github.com/litestar-org/advanced-alchemy
A carefully crafted, thoroughly tested, optimized companion library for SQLAlchemy
https://github.com/litestar-org/advanced-alchemy
alembic cockroachdb duckdb fastapi flask litestar litestar-org mssql mysql oracle-db postgresql repository-pattern sanic spanner sqlalchemy sqlite starlette
Last synced: 8 days ago
JSON representation
A carefully crafted, thoroughly tested, optimized companion library for SQLAlchemy
- Host: GitHub
- URL: https://github.com/litestar-org/advanced-alchemy
- Owner: litestar-org
- License: mit
- Created: 2023-09-05T18:45:18.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-04-12T17:40:06.000Z (9 days ago)
- Last Synced: 2025-04-13T13:56:47.337Z (8 days ago)
- Topics: alembic, cockroachdb, duckdb, fastapi, flask, litestar, litestar-org, mssql, mysql, oracle-db, postgresql, repository-pattern, sanic, spanner, sqlalchemy, sqlite, starlette
- Language: Python
- Homepage: http://docs.advanced-alchemy.litestar.dev/
- Size: 5.54 MB
- Stars: 376
- Watchers: 12
- Forks: 42
- Open Issues: 22
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.rst
- License: LICENSE
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
![]()
![]()
| Project | | Status |
|-----------|:----|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| CI/CD | | [](https://github.com/litestar-org/advanced-alchemy/actions/workflows/publish.yml) [](https://github.com/litestar-org/advanced-alchemy/actions/workflows/ci.yml) [](https://github.com/litestar-org/advanced-alchemy/actions/workflows/docs.yml) |
| Quality | | [](https://codecov.io/github/litestar-org/advanced-alchemy) [](https://sonarcloud.io/summary/new_code?id=litestar-org_advanced-alchemy) [](https://sonarcloud.io/summary/new_code?id=litestar-org_advanced-alchemy) [](https://sonarcloud.io/summary/new_code?id=litestar-org_advanced-alchemy) [](https://sonarcloud.io/summary/new_code?id=litestar-org_advanced-alchemy) |
| Package | | [](https://badge.fury.io/py/advanced-alchemy)   |
| Community | | [](https://discord.gg/litestar) [](https://matrix.to/#/#litestar:matrix.org) |
| Meta | | [](https://github.com/litestar-org/advanced-alchemy) [](https://github.com/python/mypy) [](https://spdx.org/licenses/) [](https://github.com/astral-sh/ruff) |# Advanced Alchemy
Check out the [project documentation][project-docs] 📚 for more information.
## About
A carefully crafted, thoroughly tested, optimized companion library for SQLAlchemy,
offering:- Sync and async repositories, featuring common CRUD and highly optimized bulk operations
- Integration with major web frameworks including Litestar, Starlette, FastAPI, Sanic
- Custom-built alembic configuration and CLI with optional framework integration
- Utility base classes with audit columns, primary keys and utility functions
- Built in `File Object` data type for storing objects:
- Unified interface for various storage backends ([`fsspec`](https://filesystem-spec.readthedocs.io/en/latest/) and [`obstore`](https://developmentseed.org/obstore/latest/))
- Optional lifecycle event hooks integrated with SQLAlchemy's event system to automatically save and delete files as records are inserted, updated, or deleted.
- Optimized JSON types including a custom JSON type for Oracle
- Integrated support for UUID6 and UUID7 using [`uuid-utils`](https://github.com/aminalaee/uuid-utils) (install with the `uuid` extra)
- Integrated support for Nano ID using [`fastnanoid`](https://github.com/oliverlambson/fastnanoid) (install with the `nanoid` extra)
- Pre-configured base classes with audit columns UUID or Big Integer primary keys and
a [sentinel column](https://docs.sqlalchemy.org/en/20/core/connections.html#configuring-sentinel-columns).
- Synchronous and asynchronous repositories featuring:
- Common CRUD operations for SQLAlchemy models
- Bulk inserts, updates, upserts, and deletes with dialect-specific enhancements
- Integrated counts, pagination, sorting, filtering with `LIKE`, `IN`, and dates before and/or after.
- Tested support for multiple database backends including:
- SQLite via [aiosqlite](https://aiosqlite.omnilib.dev/en/stable/) or [sqlite](https://docs.python.org/3/library/sqlite3.html)
- Postgres via [asyncpg](https://magicstack.github.io/asyncpg/current/) or [psycopg3 (async or sync)](https://www.psycopg.org/psycopg3/)
- MySQL via [asyncmy](https://github.com/long2ice/asyncmy)
- Oracle via [oracledb (async or sync)](https://oracle.github.io/python-oracledb/) (tested on 18c and 23c)
- Google Spanner via [spanner-sqlalchemy](https://github.com/googleapis/python-spanner-sqlalchemy/)
- DuckDB via [duckdb_engine](https://github.com/Mause/duckdb_engine)
- Microsoft SQL Server via [pyodbc](https://github.com/mkleehammer/pyodbc) or [aioodbc](https://github.com/aio-libs/aioodbc)
- CockroachDB via [sqlalchemy-cockroachdb (async or sync)](https://github.com/cockroachdb/sqlalchemy-cockroachdb)
- ...and much more## Usage
### Installation
```shell
pip install advanced-alchemy
```> [!IMPORTANT]\
> Check out [the installation guide][install-guide] in our official documentation!### Repositories
Advanced Alchemy includes a set of asynchronous and synchronous repository classes for easy CRUD
operations on your SQLAlchemy models.Click to expand the example
```python
from advanced_alchemy import base, repository, config
from sqlalchemy import create_engine
from sqlalchemy.orm import Mapped, sessionmakerclass User(base.UUIDBase):
# you can optionally override the generated table name by manually setting it.
__tablename__ = "user_account" # type: ignore[assignment]
email: Mapped[str]
name: Mapped[str]class UserRepository(repository.SQLAlchemySyncRepository[User]):
"""User repository."""model_type = User
db = config.SQLAlchemySyncConfig(connection_string="duckdb:///:memory:", session_config=config.SyncSessionConfig(expire_on_commit=False))
# Initializes the database.
with db.get_engine().begin() as conn:
User.metadata.create_all(conn)with db.get_session() as db_session:
repo = UserRepository(session=db_session)
# 1) Create multiple users with `add_many`
bulk_users = [
{"email": '[email protected]', 'name': 'Cody'},
{"email": '[email protected]', 'name': 'Janek'},
{"email": '[email protected]', 'name': 'Peter'},
{"email": '[email protected]', 'name': 'Jacob'}
]
objs = repo.add_many([User(**raw_user) for raw_user in bulk_users])
db_session.commit()
print(f"Created {len(objs)} new objects.")# 2) Select paginated data and total row count. Pass additional filters as kwargs
created_objs, total_objs = repo.list_and_count(LimitOffset(limit=10, offset=0), name="Cody")
print(f"Selected {len(created_objs)} records out of a total of {total_objs}.")# 3) Let's remove the batch of records selected.
deleted_objs = repo.delete_many([new_obj.id for new_obj in created_objs])
print(f"Removed {len(deleted_objs)} records out of a total of {total_objs}.")# 4) Let's count the remaining rows
remaining_count = repo.count()
print(f"Found {remaining_count} remaining records after delete.")
```For a full standalone example, see the sample [here][standalone-example]
### Services
Advanced Alchemy includes an additional service class to make working with a repository easier.
This class is designed to accept data as a dictionary or SQLAlchemy model,
and it will handle the type conversions for you.Here's the same example from above but using a service to create the data:
```python
from advanced_alchemy import base, repository, filters, service, config
from sqlalchemy import create_engine
from sqlalchemy.orm import Mapped, sessionmakerclass User(base.UUIDBase):
# you can optionally override the generated table name by manually setting it.
__tablename__ = "user_account" # type: ignore[assignment]
email: Mapped[str]
name: Mapped[str]class UserService(service.SQLAlchemySyncRepositoryService[User]):
"""User repository."""
class Repo(repository.SQLAlchemySyncRepository[User]):
"""User repository."""model_type = User
repository_type = Repo
db = config.SQLAlchemySyncConfig(connection_string="duckdb:///:memory:", session_config=config.SyncSessionConfig(expire_on_commit=False))
# Initializes the database.
with db.get_engine().begin() as conn:
User.metadata.create_all(conn)with db.get_session() as db_session:
service = UserService(session=db_session)
# 1) Create multiple users with `add_many`
objs = service.create_many([
{"email": '[email protected]', 'name': 'Cody'},
{"email": '[email protected]', 'name': 'Janek'},
{"email": '[email protected]', 'name': 'Peter'},
{"email": '[email protected]', 'name': 'Jacob'}
])
print(objs)
print(f"Created {len(objs)} new objects.")# 2) Select paginated data and total row count. Pass additional filters as kwargs
created_objs, total_objs = service.list_and_count(LimitOffset(limit=10, offset=0), name="Cody")
print(f"Selected {len(created_objs)} records out of a total of {total_objs}.")# 3) Let's remove the batch of records selected.
deleted_objs = service.delete_many([new_obj.id for new_obj in created_objs])
print(f"Removed {len(deleted_objs)} records out of a total of {total_objs}.")# 4) Let's count the remaining rows
remaining_count = service.count()
print(f"Found {remaining_count} remaining records after delete.")
```### Web Frameworks
Advanced Alchemy works with nearly all Python web frameworks.
Several helpers for popular libraries are included, and additional PRs to support others are welcomed.#### Litestar
Advanced Alchemy is the official SQLAlchemy integration for Litestar.
In addition to installing with `pip install advanced-alchemy`,
it can also be installed as a Litestar extra with `pip install litestar[sqlalchemy]`.Litestar Example
```python
from litestar import Litestar
from litestar.plugins.sqlalchemy import SQLAlchemyPlugin, SQLAlchemyAsyncConfig
# alternately...
# from advanced_alchemy.extensions.litestar import SQLAlchemyAsyncConfig, SQLAlchemyPluginalchemy = SQLAlchemyPlugin(
config=SQLAlchemyAsyncConfig(connection_string="sqlite+aiosqlite:///test.sqlite"),
)
app = Litestar(plugins=[alchemy])
```For a full Litestar example, check [here][litestar-example]
#### Flask
Flask Example
```python
from flask import Flask
from advanced_alchemy.extensions.flask import AdvancedAlchemy, SQLAlchemySyncConfigapp = Flask(__name__)
alchemy = AdvancedAlchemy(
config=SQLAlchemySyncConfig(connection_string="duckdb:///:memory:"), app=app,
)
```For a full Flask example, see [here][flask-example]
#### FastAPI
FastAPI Example
```python
from advanced_alchemy.extensions.fastapi import AdvancedAlchemy, SQLAlchemyAsyncConfig
from fastapi import FastAPIapp = FastAPI()
alchemy = AdvancedAlchemy(
config=SQLAlchemyAsyncConfig(connection_string="sqlite+aiosqlite:///test.sqlite"), app=app,
)
```For a full FastAPI example with optional CLI integration, see [here][fastapi-example]
#### Starlette
Pre-built Example Apps
```python
from advanced_alchemy.extensions.starlette import AdvancedAlchemy, SQLAlchemyAsyncConfig
from starlette.applications import Starletteapp = Starlette()
alchemy = AdvancedAlchemy(
config=SQLAlchemyAsyncConfig(connection_string="sqlite+aiosqlite:///test.sqlite"), app=app,
)
```#### Sanic
Pre-built Example Apps
```python
from sanic import Sanic
from sanic_ext import Extendfrom advanced_alchemy.extensions.sanic import AdvancedAlchemy, SQLAlchemyAsyncConfig
app = Sanic("AlchemySanicApp")
alchemy = AdvancedAlchemy(
sqlalchemy_config=SQLAlchemyAsyncConfig(connection_string="sqlite+aiosqlite:///test.sqlite"),
)
Extend.register(alchemy)
```## Contributing
All [Litestar Organization][litestar-org] projects will always be a community-centered, available for contributions of any size.
Before contributing, please review the [contribution guide][contributing].
If you have any questions, reach out to us on [Discord][discord], our org-wide [GitHub discussions][litestar-discussions] page,
or the [project-specific GitHub discussions page][project-discussions].
![]()
An official Litestar Organization Project
[litestar-org]: https://github.com/litestar-org
[contributing]: https://docs.advanced-alchemy.litestar.dev/latest/contribution-guide.html
[discord]: https://discord.gg/litestar
[litestar-discussions]: https://github.com/orgs/litestar-org/discussions
[project-discussions]: https://github.com/litestar-org/advanced-alchemy/discussions
[project-docs]: https://docs.advanced-alchemy.litestar.dev
[install-guide]: https://docs.advanced-alchemy.litestar.dev/latest/#installation
[fastapi-example]: https://github.com/litestar-org/advanced-alchemy/blob/main/examples/fastapi_service.py
[flask-example]: https://github.com/litestar-org/advanced-alchemy/blob/main/examples/flask/flask_services.py
[litestar-example]: https://github.com/litestar-org/advanced-alchemy/blob/main/examples/litestar.py
[standalone-example]: https://github.com/litestar-org/advanced-alchemy/blob/main/examples/standalone.py