En una rama nueva (
feat/migraciones-seguras) con copia de tu BD. No mires solutions.md hasta entregar.
Ejercicio 1 — El renombrado sin caída
Modelo: tu evento tiene title (si ya se llama así, crea un campo gemelo temporal para el ejercicio).
- Añade
label = CharField(null=True)(EXPAND) y migra. - Escribe la migración de datos que copia
title → labelpor lotes (pkpaginado), con reverse noop. - Cambia el código para escribir/leer
label(dual write: guarda en ambos). Demuestra con shell que ambas columnas quedan iguales tras crear 3 eventos. - Simula el SWITCH (el código ya solo usa label) y escribe la migración CONTRACT que elimina
title. ¿Qué rompería ejecutar el código viejo justo después de este paso?
Ejercicio 2 — El NOT NULL peligroso, hecho seguro
- Intenta
AddField(field=CharField(max_length=16, null=False, default=""))sobre una tabla con filas: ¿qué genera Django y qué hace PostgreSQL? - Hazlo por el camino largo: añadir nullable → backfill con RunPython por lotes →
AlterFielda NOT NULL. Verifica el tiempo de cada paso conEXPLAIN-mental (o \timing en los pasos SQL). - Instala
django-migration-lintery corre el lint sobre tu app: ¿marca operaciones peligrosas de tu historial?
Ejercicio 3 — Índice CONCURRENTLY
- En una migración con
atomic = False, crea conRunSQLun índice CONCURRENTLY sobre una columna consultada (p. ej.reservation.created_at). - Intenta lo mismo sin CONCURRENTLY en una tabla grande (o simula con 100k filas): ¿bloquea escrituras mientras corre? ¿Qué pasa si falla a medias el CONCURRENTLY (índice INVALID)?
- Escribe el check para detectar índices INVALID:
SELECT * FROM pg_index WHERE NOT indisvalid;
Ejercicio 4 — Las 3 mejoras de la 08
Aplica tus mejoras anotadas con migraciones seguras (una por mejora, lint verde):
- NOT NULL con backfill donde corresponda.
- CHECK de coherencia (
expires_at > created_aten reservation) — ¿qué pasa con filas viejas que lo violan? (backfill/corrección primero). slugúnico en evento con generación para el histórico.
Entrega
Pega migraciones y outputs. Cierra la 11; después Lección 12 — NoSQL.