SQLAlchemy Easy SoftDelete

raw JSON →
0.9.0 verified Sat May 09 auth: no python

Provides a mixin and utilities to add soft-deletion (deleted_at column) to SQLAlchemy ORM models. Version 0.9.0 supports SQLAlchemy 2.x and requires Python >=3.10. Actively maintained.

pip install sqlalchemy-easy-softdelete
error ImportError: cannot import name 'SoftDeleteMixin' from 'sqlalchemy_easy_softdelete'
cause SoftDeleteMixin is located in the mixin submodule, not the package root.
fix
Use: from sqlalchemy_easy_softdelete.mixin import SoftDeleteMixin
error TypeError: metaclass conflict: the metaclass of a derived class must be a subclass of the metaclasses of all its bases
cause Mixing SoftDeleteMixin with a Base that uses a different metaclass (e.g., from Flask-SQLAlchemy).
fix
Ensure Base uses DeclarativeBase from SQLAlchemy (or use the provided Base from the mixin module).
gotcha The library overrides session.delete() to set deleted_at instead of hard deleting. This can be surprising if you expect actual deletion; hard deletion must be done with session.execute(delete(...)).
fix Use session.execute() with a DELETE statement for hard deletes.
deprecated Versions before 0.7.0 used a different mixin location (from sqlalchemy_easy_softdelete import SoftDeleteMixin). That import path no longer works.
fix Update import to from sqlalchemy_easy_softdelete.mixin import SoftDeleteMixin.
gotcha The library automatically filters out soft-deleted records when querying. To include them, you must use with_deleted() method on the query.
fix Use query = session.query(User).with_deleted() to include soft-deleted rows.

Defines a model with soft-delete support. The delete() method on the session performs a soft delete by setting deleted_at timestamp.

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy_easy_softdelete.mixin import SoftDeleteMixin

engine = create_engine('sqlite:///:memory:')

class Base(DeclarativeBase):
    pass

class User(SoftDeleteMixin, Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)

Base.metadata.create_all(engine)

from sqlalchemy.orm import Session
with Session(engine) as session:
    user = User(name='Alice')
    session.add(user)
    session.commit()
    session.delete(user)  # This will soft-delete
    session.commit()