DRF en tu proyecto. No mires solutions.md hasta entregar.
Ejercicio 1 — La superficie completa
- Escribe la tabla de rutas de TicketFlow completa (como la de la lección) incluyendo: registro/login (adelanto de la 18), eventos, asientos, disponibilidad, reservas, pagos, webhook, tarjetas regalo.
- Para cada ruta: verbo(s), auth necesaria (público / dueño / organizador / sistema), y código de éxito.
- Crítica la tuya: ¿algún verbo en la ruta? ¿algún anidamiento >1 nivel? ¿alguno sin plural?
Ejercicio 2 — Handler RFC 7807
- Implementa
custom_exception_handler(exc, context)en DRF que produzca el formato de la lección para: ValidationError (400), Http404 (404), PermissionDenied (403), tu excepción de dominio (409/422). - Define
DomainError(code, status, title, detail)y lánzala desdereservar()de la 10 cuando el asiento esté ocupado; verifica el cuerpo JSON resultante. - ¿Qué pasa con
Detail: Noneen errores sin detalle? Decide el campo mínimo obligatorio y justifícalo.
Ejercicio 3 — Paginación de verdad
- Configura cursor pagination en el listado de eventos y offset en el panel de admin (settings de DRF: dos paginadores). Verifica las respuestas (
next,previous,results). - Genera 500 eventos y compara
?page=999(offset) vs cursor profundo: mide tiempos conEXPLAIN ANALYZEdetrás. - Añade filtros con django-filter:
state,starts_after,orderingcon whitelist (solostarts_at,title,-starts_at).
Ejercicio 4 — UUID público
- Añade
uuid = UUIDField(default=uuid4, unique=True, editable=False)a Event y Reservation (migración segura de la 11). - Cambia lookup a
lookup_field = "uuid"en tus viewsets y serializers. Verifica que/api/events/{entero}/devuelve 404 y el UUID 200. - ¿Debería la reserva del usuario A ser enumerable por el usuario B con el UUID correcto? ¿Qué capa lo impide (adelanto 21)?
Ejercicio 5 — El contrato de headers: ETag, Vary y Cabeceras de API
- Añade el
ETagal detalle de evento (con elupdated_atdel recurso, la 38) y verifica: segunda petición conIf-None-Match→ 304 vacío. ¿Qué ahorra tu ancho de banda el día del pico? - Añade
Vary: Accept-Encodingal proxy o a la respuesta y comprueba con curl que el 304 distingue cliente gzip de cliente plano (39). - Cabeceras de la plataforma: añade a TODAS las respuestas
X-Request-ID(el trace_id de la 45),X-RateLimit-Remaining(23) yX-Content-Type-Options: nosniff. Test de contrato: las tres presentes en un 200 y en un 409.
Entrega
Pega rutas, código del handler y salidas. Después: Lección 14 — Idempotencia y versionado.