Skip to main content

SQLAlchemy ORM with Async Support

This project provides an abstract base class Model with advanced CRUD operations, audit logging, and support for SQLAlchemy's async ORM functionality. It includes several useful features such as soft delete functionality, Pydantic model integration for validation, and audit logging with event listeners.

Key Features

  • Async Session Management: Provides session management using async SQLAlchemy.
  • CRUD Operations: Includes create, read, update, and delete operations.
  • Soft Delete (opt-in): Ability to soft-delete records by marking them as inactive.
  • Audit Logging (opt-in): Logs changes to models (insert, update, delete).
  • Pydantic Model Integration: Supports data validation using Pydantic models.
  • Event Listeners: Event listeners automatically trigger audit logging on inserts, updates, and deletes.
  • Transaction Management: Supports transactional operations with rollback on failure.
  • Pagination Support: Allows for paginated queries and returns results with metadata.
  • Bulk Operations: Provides bulk create, update, and delete functionality.

Installation

pip install sqla-async-orm-queries

Alternatively, if you prefer to use poetry for package dependencies:

poetry shell
poetry add sqla-async-orm-queries

Usage Examples Before using this code, ensure you have the following dependency installed:

Python 3.11 or above

How to Use

1. Define a Model

To define your own model, inherit from the Model class and define your fields using SQLAlchemy's Column types. Each model can also define its own Pydantic schema for validation purposes.

from typing import Optional

from sqlalchemy import Column, Integer, String
from sqla_async_orm_queries.models import Model, PydanticModelMixin

class User(Model):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    email = Column(String, unique=True, nullable=False)

    class PydanticModel(PydanticModelMixin):
        id: Optional[int]
        name: str
        email: str

2. Initialize the Session

You need to initialize the session factory to enable database operations. Make sure to provide an async_sessionmaker for managing async sessions.

from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
from sqla_async_orm_queries.models import Model, PydanticModelMixin

DATABASE_URL = "sqlite+aiosqlite:///:memory:"

engine = create_async_engine(DATABASE_URL)
SessionLocal = async_sessionmaker(bind=engine, expire_on_commit=False)

Model.init_session(SessionLocal)

3. Perform CRUD Operations

CRUD operations are supported out of the box. You can create, read, update, delete, and soft delete records using the provided methods.

# Create a new user
user_data = {'name': 'John Doe', 'email': 'john@example.com'}
user = await User.create(user_data)

# Read a user
user = await User.select_one(User.id == 1)

# Update a user
await User.update({'name': 'Jane Doe'}, User.id == 1)

# Soft delete a user (the model needs SoftDeleteMixin: class User(SoftDeleteMixin, Model))
await User.soft_delete(User.id == 1)

4. Audit Logging

Audit logging is opt-in. Import AuditLog (this adds the audit_logs table) and attach listeners to the models you want logged:

from sqla_async_orm_queries.audit import AuditLog

User.attach_listeners()

audit_logs = await AuditLog.select_all()

5. Transaction Management

The transactional method provides an easy way to run a set of operations inside a transaction. If any error occurs, the transaction will be rolled back.

async def my_operations(session):
    await User.create({'name': 'New User', 'email': 'new_user@example.com'}, session=session)

await User.transactional(my_operations)

If you pass your own session, methods don't commit — you do, once, at the end:

async with SessionLocal() as session:
    await User.create({'name': 'New User', 'email': 'new_user@example.com'}, session=session)
    await User.execute_query_write(update(User).where(User.id == 1).values(name='Jane'), session=session)
    await session.commit()

6. Bulk Operations

You can create, update, and delete multiple records in a single transaction using the bulk_create, bulk_update, and bulk_delete methods.

# Bulk create users
users_data = [{'name': 'User 1', 'email': 'user1@example.com'}, {'name': 'User 2', 'email': 'user2@example.com'}]
await User.bulk_create(users_data)

# Bulk delete users
await User.bulk_delete([User.id == 1, User.id == 2])

7. Pagination

Paginate through results using the select_with_pagination method:

pagination = await User.select_with_pagination(page=2, per_page=10)
print(pagination.items)  # The users on the second page

Upgrading to 3.0

Soft delete and audit logging are now opt-in. If you use them, add SoftDeleteMixin to those models and import sqla_async_orm_queries.audit. Requires Python 3.11+. Install your database driver (e.g. asyncpg) yourself.

Installation

pip install sqla-async-orm-queries
pip install asyncpg  # or your database driver, e.g. aiosqlite

Running Tests

poetry install
make test

License

This project is licensed under the MIT License.

Metadata

Release files for sqla-async-orm-queries 3.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sqla-async-orm-queries 3.0.0
File Size Uploaded Provenance
sqla_async_orm_queries-3.0.0.tar.gz 7.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for sqla-async-orm-queries 3.0.0
File Interpreter ABI Platform
sqla_async_orm_queries-3.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 16.6 kB

Release files / sqla_async_orm_queries-3.0.0.tar.gz

Download URL sqla_async_orm_queries-3.0.0.tar.gz
Size 7.7 kB
Tags Source
SHA-256 checksum
How to use checksums
d57f361fdd11fcfe30c73fa9ec7ad298d958736caa1bc6035e0d0b394f58e5b8
BLAKE2b-256 checksum
How to use checksums
e496cade0db183134edf8c9e08363f8a79c7c3b2411fb12ff9513fe3fc27f23a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.5.1 CPython/3.13.16 Linux/6.17.0-1022-azure

Release files / sqla_async_orm_queries-3.0.0-py3-none-any.whl

Download URL sqla_async_orm_queries-3.0.0-py3-none-any.whl
Size 8.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
27e364491a37c62e74f6f854b4210be8a43cf415fe8e97454a919d4e79421a12
BLAKE2b-256 checksum
How to use checksums
6281c13bc52faf8fc258e369f5430f70c09265c094daf3ead7fc9baa1805d698
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.5.1 CPython/3.13.16 Linux/6.17.0-1022-azure

Security for sqla-async-orm-queries 3.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page