fast-database
Shared SQLAlchemy ORM models for FastMVC applications: one declarative Base, table name constants, and models for users/auth, organizations, subscriptions, payments, commerce (cart/orders/shipments), webhooks, notifications, LLM conversation threads, per-user encrypted LLM provider API keys (BYOK), user messaging (chats, messages, read receipts, notification delivery), personal ledger / Pure.cam–aligned tables, and audit logs.
Operational / production patterns baked into the schema include: idempotency (IdempotencyRecord), transactional outbox (OutboxEvent), one-time tokens (UserOneTimeToken), login attempt history (UserLoginEvent), consent (ConsentRecord), plus SystemSetting (runtime toggles), UserMfaFactor (MFA enrollment), DataExportRequest (GDPR-style exports), SecurityEvent (SIEM-friendly signals), and UsageCounter (quota / metering buckets).
The same wheel also ships fast_database.repositories: IRepository, FilterOperator, and concrete repository classes for the tables above (same import paths as before).
Python: 3.10+ · Dependencies: sqlalchemy>=2,<3, loguru, cachetools
Import packages: fast_database, fast_database.repositories
PyPI distribution name: fast-database (hyphenated)
Layout
fast_database.models—Baseand all table classes.fast_database.constants.db.table—Table— centralized string names for__tablename__.fast_database.mixins—TimestampMixin,UUIDPrimaryKeyMixin,SoftDeleteMixin,OrganizationScopedMixin,TenantIdMixin,OptimisticLockMixin,AuditActorMixin.fast_database.optimistic_lock—assert_version_matches,expected_version,StaleVersionErrorfor service-layer checks.fast_database.soft_delete—select_active,where_not_deleted,mark_soft_deleted,restore_soft_deleted,filter_active.fast_database.factories(optional[dev]extra, includesfactory-boy) — examplePlanFactoryfor tests.fast_database.repositories—FilterOperator,IRepository, and per-entity repositories (e.g.from fast_database.repositories.user import UserRepository).
Mixins (new tables)
from sqlalchemy import Column, String
from fast_database import Base, TimestampMixin, UUIDPrimaryKeyMixin, SoftDeleteMixin
class Widget(Base, UUIDPrimaryKeyMixin, TimestampMixin, SoftDeleteMixin):
__tablename__ = "widgets"
label = Column(String(255), nullable=False)
Tenant-scoped rows (composite indexes)
Use OrganizationScopedMixin (organization_id → organizations.id) or TenantIdMixin (generic tenant_id without FK). Add a composite index for common filters:
from sqlalchemy import Column, Index, Integer, String
from fast_database import Base, OrganizationScopedMixin
class InvoiceLine(Base, OrganizationScopedMixin):
__tablename__ = "invoice_lines"
__table_args__ = (Index("ix_invline_org_external", "organization_id", "external_ref"),)
id = Column(Integer, primary_key=True)
external_ref = Column(String(64), nullable=False)
Optimistic locking
Add OptimisticLockMixin and map version with :func:sqlalchemy.orm.declared_attr (see docstring on the mixin). Use assert_version_matches(instance, client_version) before applying updates from the API.
Audit actor columns
AuditActorMixin adds nullable created_by_id / updated_by_id FKs to user.id (set from the current user in services).
factory_boy (tests)
pip install 'fast-database[dev]'
from fast_database.factories import PlanFactory
# Bind PlanFactory._meta.sqlalchemy_session to your test session, then:
plan = PlanFactory()
Alembic autogenerate
- Point Alembic at the same metadata as your app:
target_metadata = Base.metadata(importBasefromfast_database). - Ensure
env.pyloads all model modules so every table is registered onBase.metadatabefore autogenerate runs (otherwise Alembic will propose dropping “unknown” tables).
Example fragment for migrations/env.py (adjust imports to your project layout):
# Load ORM models so Base.metadata is complete before autogenerate.
import fast_database.models # noqa: F401 — registers all tables on Base
from fast_database.models import Base
target_metadata = Base.metadata
# In run_migrations_online(), pass target_metadata to context.configure(
# ...
# target_metadata=target_metadata,
# compare_type=True,
# compare_server_default=True,
# )
Then:
alembic revision --autogenerate -m "describe change"
alembic upgrade head
Review autogenerated diffs carefully (renames are not always detected; constraints may need hand edits).
Install
pip install -e ./fast_database
Or from PyPI (when published):
pip install fast-database
Pair with fast_db so your app’s engine uses the same metadata for Alembic migrations.
For tests with factory_boy examples: pip install 'fast-database[dev]'.
Related packages
fast_db— engine and sessions.- Monorepo: ../README.md.
Tooling
See CONTRIBUTING.md, Makefile, and PUBLISHING.md.
Documentation
| Document | Purpose |
|---|---|
| CONTRIBUTING.md | Dev setup, tests, monorepo sync |
| PUBLISHING.md | PyPI and releases |
| SECURITY.md | Reporting vulnerabilities |
| CHANGELOG.md | Version history |
Monorepo: ../README.md · Coverage: ../docs/COVERAGE.md
Metadata
Release files for fast-database 1.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fast_database-1.6.0.tar.gz | 128.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fast_database-1.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 344.9 kB
Release files / fast_database-1.6.0.tar.gz
| Download URL | fast_database-1.6.0.tar.gz |
|---|---|
| Size | 128.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e922e20edb968f3da8afde8cb8ff8e9b6fdf7895623caf6191513db76b894851
|
|
BLAKE2b-256 checksum How to use checksums |
714cb8ac8284914a944db043ad3cbf3855e5cf077fefeb81b3c2f0d6ad90f749
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Release files / fast_database-1.6.0-py3-none-any.whl
| Download URL | fast_database-1.6.0-py3-none-any.whl |
|---|---|
| Size | 216.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
084d13baefadc59a69629559c6e5bf5ccb5b0c0a33a95831f6ea131123c9f562
|
|
BLAKE2b-256 checksum How to use checksums |
ae5e5c28753fcfc859468e444b145a8835bb0dbb9fbd1dbfa0c0a34af6078035
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|