Soft delete mixin for SQLAlchemy — never lose data again
Project description
sqlalchemy-soft-delete
A lightweight SQLAlchemy mixin that adds soft delete to any model. Instead of permanently removing rows, it sets a deleted_at timestamp — so you never lose data again.
Features
- Drop-in mixin — add
SoftDeleteMixinto any model and you're done deleted_attimestamp — know exactly when a row was deletedis_deletedhybrid property — use in Python and in SQL queriessoft_delete()/restore()— intuitive instance methodswith_deleted()helper — bypass the filter when you need to see everything- SQLAlchemy 2.0+ native — built on
Mapped,mapped_column, andhybrid_property - Zero dependencies beyond SQLAlchemy itself
- Fully typed — works great with mypy and IDE autocompletion
Installation
pip install sqlalchemy-soft-delete
Quick Start
Before (hard delete)
session.delete(user) # Gone forever
session.commit()
After (soft delete)
from sqlalchemy_soft_delete import SoftDeleteMixin
class User(SoftDeleteMixin, Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
# Soft delete — row stays in the database
user.soft_delete()
session.commit()
# Restore whenever you need
user.restore()
session.commit()
Usage
Soft deleting a row
user = session.get(User, 1)
user.soft_delete()
session.commit()
print(user.is_deleted) # True
print(user.deleted_at) # 2026-04-17 12:34:56+00:00
Restoring a soft-deleted row
user.restore()
session.commit()
print(user.is_deleted) # False
print(user.deleted_at) # None
Querying only active rows
from sqlalchemy import select
# Filter out deleted rows explicitly
stmt = select(User).where(~User.is_deleted)
active_users = session.execute(stmt).scalars().all()
Querying all rows (including deleted)
# No filter — returns everything
stmt = select(User)
all_users = session.execute(stmt).scalars().all()
Querying only deleted rows
stmt = select(User).where(User.is_deleted)
deleted_users = session.execute(stmt).scalars().all()
API Reference
SoftDeleteMixin
| Member | Type | Description |
|---|---|---|
deleted_at |
Mapped[datetime | None] |
UTC timestamp of deletion, None if active |
is_deleted |
hybrid_property |
True if soft-deleted; usable in Python and SQL |
soft_delete() |
method | Sets deleted_at to current UTC time |
restore() |
method | Clears deleted_at back to None |
with_deleted(query)
Marks a legacy Query object to include soft-deleted rows via execution options.
Requirements
- Python 3.10+
- SQLAlchemy 2.0+
License
MIT License. See LICENSE for details.
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
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sqlalchemy_soft_delete-0.1.0.tar.gz.
File metadata
- Download URL: sqlalchemy_soft_delete-0.1.0.tar.gz
- Upload date:
- Size: 5.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1c6418fc03f634268de9ad900f2dc7c6f5c3c4b9b1b666511531946f7824b2ac
|
|
| MD5 |
354d7c3d9e22e3addda2be2381b516d3
|
|
| BLAKE2b-256 |
22383b8abfd545bc31c464ef70df3ed1a8cbbd09a9fc2599bd3e31671566ed08
|
File details
Details for the file sqlalchemy_soft_delete-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sqlalchemy_soft_delete-0.1.0-py3-none-any.whl
- Upload date:
- Size: 5.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f868dda19ef98130a10318cde5a37b90bf0834cfbb98ca065bbbc4a60c15f002
|
|
| MD5 |
4272950a7bce83ac1cda2b2f92952031
|
|
| BLAKE2b-256 |
84fdfa6dd85a0a413fd757b5b9966e73cc2a56bc1bb52c4c47568c00ccc28c46
|