Empezando¶
Recorrido de 10 minutos desde "no lo he instalado" hasta "he insertado y consultado filas de verdad". Sin FastAPI ni async — solo lo básico. Para la versión async / FastAPI salta al Tutorial.
1. Instalar¶
Para PostgreSQL: pip install "djanorm[postgresql]".
Para MySQL / MariaDB (3.1+): pip install "djanorm[mysql]"
(pure-Python pymysql + aiomysql, sin C toolchain).
Para uploads en S3: pip install "djanorm[s3]" (funciona con AWS S3,
MinIO, Cloudflare R2, Backblaze B2).
2. Crear el esqueleto del proyecto¶
Esto crea:
.
├── blog/
│ ├── __init__.py
│ └── models.py # User de ejemplo
└── settings.py # bloques DATABASES y STORAGES comentados
El settings.py generado incluye plantillas comentadas tanto para
SQLite/PostgreSQL como para STORAGES de almacenamiento de archivos
(disco local, AWS S3 y MinIO/S3-compatible). Descomenta las que
necesites.
3. Configurar la base de datos¶
Abre settings.py y descomenta la sección de SQLite:
dorm autodescubre cualquier directorio hermano que tenga __init__.py
+ models.py, así que para el caso simple no necesitas INSTALLED_APPS.
4. Definir tus modelos¶
Edita blog/models.py:
import dorm
class Author(dorm.Model):
name = dorm.CharField(max_length=100)
email = dorm.EmailField(unique=True)
bio = dorm.TextField(null=True, blank=True)
class Meta:
ordering = ["name"]
class Post(dorm.Model):
title = dorm.CharField(max_length=200)
body = dorm.TextField()
author = dorm.ForeignKey(Author, on_delete=dorm.CASCADE, related_name="posts")
published = dorm.BooleanField(default=False)
created_at = dorm.DateTimeField(auto_now_add=True)
5. Crear y aplicar migraciones¶
Verás:
Detecting changes for 'blog'...
Created migration: blog/migrations/0001_initial.py
Applying blog.0001_initial... OK
6. Insertar y consultar¶
Entra en la shell de dorm — pre-importa tus modelos y usa IPython si está disponible:
>>> alice = Author.objects.create(name="Alice", email="alice@example.com")
>>> Post.objects.create(title="Hello", body="World", author=alice, published=True)
<Post: pk=1>
>>> Author.objects.count()
1
>>> for p in Post.objects.filter(published=True).select_related("author"):
... print(p.author.name, "—", p.title)
Alice — Hello
>>> # Expresiones F, objetos Q, agregaciones — todo está aquí
>>> from dorm import F, Q, Count
>>> Author.objects.annotate(post_count=Count("posts")).values_list("name", "post_count")
[('Alice', 1)]
7. Pasar a PostgreSQL¶
Cuando estés listo para dejar SQLite, lo único que cambia es
settings.py:
DATABASES = {
"default": {
"ENGINE": "postgresql",
"NAME": "blog",
"USER": "postgres",
"PASSWORD": "secreto",
"HOST": "localhost",
"PORT": 5432,
}
}
Lanza dorm migrate contra la BD vacía de PG. Tu código, modelos y
consultas no cambian.
8. MySQL / MariaDB (3.1+)¶
Instala el extra y apunta al servicio MySQL:
DATABASES = {
"default": {
"ENGINE": "mysql", # o "mariadb"
"NAME": "blog",
"USER": "root",
"PASSWORD": "secreto",
"HOST": "localhost",
"PORT": 3306,
}
}
Caveats: DDL no es transaccional en MySQL — envolver ALTER TABLE
en atomic() no lo revierte. RETURNING funciona en MariaDB
10.5+ pero no en MySQL; el insert usa cursor.lastrowid para PKs
autoincrement. El wrapper fuerza ANSI_QUOTES para que los
identificadores entre comillas dobles parseen igual que en
PostgreSQL / SQLite.
9. DuckDB para analítica embarcada (4.0+)¶
Cuando tu workload es analítico (dashboards, ETL local, ML feature stores) en lugar de OLTP, el backend DuckDB ejecuta queries columnar en proceso, sin servidor.
DATABASES = {
"default": {
"ENGINE": "duckdb",
"NAME": "analytics.duckdb", # archivo en disco; ":memory:" también vale
}
}
Tu código sigue idéntico — Author.objects.filter(...),
bulk_create, agregaciones. Caveat: DuckDB no tiene SAVEPOINT,
así que atomic() anidado degrada a no-op boundary; el rollback
externo descarta todo. Más detalle en DuckDB.
Para OLTP serio sigue PostgreSQL — DuckDB brilla en lecturas vectorizadas masivas, no en escrituras concurrentes.
¿Qué sigue?¶
- Modelos y campos — todos los tipos y sus opciones
- Consultas — filter, exclude, Q, F, agregaciones
- Patrones async —
acreate,aiterator,aatomic - Tutorial — montarlo con FastAPI
- Novedades 4.0 — overview de las features 4.0
- DuckDB — backend OLAP embarcado
- Subida de archivos con
FileField— disco local por defecto, cambia a S3 / MinIO / R2 con un cambio enSTORAGES