djanorm¶
A Django-style ORM for Python with first-class async, FastAPI-ready
Pydantic schemas, and a tiny dorm CLI. No Django runtime needed.
import dorm
class Author(dorm.Model):
name = dorm.CharField(max_length=100)
age = dorm.IntegerField()
# Sync
alice = Author.objects.create(name="Alice", age=30)
adults = Author.objects.filter(age__gte=18).order_by("name")
# Async — every method has an `a*` variant
alice = await Author.objects.acreate(name="Alice", age=30)
async for a in Author.objects.filter(age__gte=18):
print(a.name)
Where to start¶
| If you're… | Read… |
|---|---|
| brand new | Getting started |
| building a FastAPI app | Tutorial: 5 minutes to your first API |
| coming from Django | Migration from Django ORM |
| looking up what changed in 4.0 | What's new in 4.0 |
| not sure which helper to use | When to use what |
| looking up a method | API Reference (sidebar) |
| putting this in prod | Production deployment |
Why dorm¶
- Same QuerySet API as Django —
filter,exclude,Q,F,bulk_create,select_related,prefetch_related, signals, the works. If you know Django, you already know dorm. - Sync and async — every method has an
a*variant. The async pool retries on transient errors and logs slow queries out of the box.AsyncModelrejects sync API for async-only stacks. - Type-safe —
Field[T]generics +Manager[Self]. Thedjanorm-mypyplugin validatesfilter()kwargs against the model and lookup suffixes at compile time. - FastAPI-friendly —
DormSchema+list_response_schema+nested_schema_for+schema_with_computed. StreamingStreamingResponsedirectly viadorm.contrib.streaming. No glue. - Production hardening built in — circuit breaker, query budget
(HTTP SLA timeout), pool task affinity, lag-aware read routing,
outbox pattern, hash sharding, idempotency keys, schema-drift
detection (
dorm diff). - Multi-backend — SQLite, PostgreSQL, MySQL/MariaDB, libsql/Turso, and from 4.0 DuckDB (embedded analytics). Same models, same migrations.
- First-class PG features —
COPY FROM/TO, materialised views, declarative partitioning (RANGE/LIST/HASH), asyncLISTEN/NOTIFYpub-sub,pgvector,HStoreField, native ENUM types, full-text search with trigram + GIN. - Zero-downtime migrations —
AddFieldOnline+BackfillBatch+SetNotNullOnlinefor big tables in production. - Multi-tenancy — schema-level (
dorm.contrib.tenants) or row-level (TenantModel+current_tenant()). - Tooling extracted —
pytest-djanormanddjanorm-mypyship as sibling packages so the main wheel never pulls dev tooling (rationale). - Pluggable file storage —
FileFieldwrites to local disk by default and to AWS S3 / MinIO / Cloudflare R2 / Backblaze B2 by changingsettings.STORAGES. Application code doesn't change.
Install¶
pip install "djanorm[sqlite]"
pip install "djanorm[postgresql]"
pip install "djanorm[duckdb]" # embedded analytics (4.0+)
pip install "djanorm[sqlite,postgresql,pydantic]"
# Uploads on AWS S3 / MinIO / R2 / B2
pip install "djanorm[postgresql,s3]"
# Dev tooling (sibling packages)
pip install pytest-djanorm djanorm-mypy
Quick reference¶
- Model definition → Models & fields
- Query API → Querying
- Async patterns → Async patterns
- Schema migrations → Migrations
- Zero-downtime migrations → Online migrations
- Transactions → Transactions
- FastAPI / Pydantic → FastAPI integration
- DuckDB backend → DuckDB
- Row-level multi-tenancy → Row tenancy
- Recursive CTEs / trees → Recursive CTE
- Framework-agnostic helpers → Helpers
- Advanced PG features → Advanced
- Sibling packages (mypy / pytest) → Sibling packages
- Benchmark vs other ORMs → Bench
dormcommand line → CLI reference- File uploads (local disk / S3 / MinIO) → Models: Files
- Going live → Production deployment
- Stuck on something → Troubleshooting