Lista de cotejo: cómo se evalúa cada Unidad
Este documento explica, paso a paso, exactamente qué se revisa al cerrar la Unidad 1 y la Unidad 2 — qué porcentaje pesa cada componente, qué ítems concretos de tus guías semanales se marcan como cumplidos, qué tipo de pregunta cae en el examen conceptual y qué reto de live coding puedes esperar. No hay sorpresas: todo lo que aparece aquí es la misma Matriz de Evaluación Anti-IA del curso, aplicada en detalle a cada Unidad.
Front-End Esencial
Semanas 1-2 · Portafolio HTML5 + Tailwind + RenderSe evalúa con las cuatro fuentes de evidencia de la Matriz Anti-IA del curso, aplicadas sobre lo construido en las guías de la Semana 1 y la Semana 2: el portafolio semántico desplegado en Render y su rediseño responsivo con Tailwind.
Ponderación de la Unidad
Los mismos cuatro componentes de la Matriz Anti-IA (ver Anexo C), con ejemplos concretos de la Unidad 1.
3-5 min: se te pide modificar tu propio HTML/Tailwind en vivo (ver 1.3).
Presencial, sin dispositivos: HTML semántico, utility-first CSS, mobile-first (ver 1.4).
Historial semanal con progresión real, no un commit único de último momento (ver 1.5).
La URL de Render debe responder en el momento de la revisión (ver checklist 1.2).
Lista de cotejo funcional (15% "Entregable publicado")
Cada ítem corresponde a un punto ya practicado en las guías de Semana 1 y 2. El docente lo verifica abriendo tu URL de Render y tu repo de GitHub en vivo.
| ✓ | Ítem a verificar | Cómo se verifica |
|---|---|---|
| Estructura HTML5 semántica completa | header, nav, main con 2+ section, footer — visibles en el HTML fuente | |
| Navegación por teclado funcional | Tab recorre header → nav → main → footer con foco visible | |
| Repositorio en GitHub con historial real | Al menos 2 commits fechados, uno por semana, con mensajes descriptivos | |
| Sitio publicado en Render (Static Site) | URL https://...onrender.com responde con HTTPS en el momento de la revisión | |
| Formulario de contacto con validación HTML5 | required, type="email", minlength/maxlength — probado dejando un campo vacío | |
| Tailwind CDN activo y aplicado | Estilos visibles; no queda HTML sin clases de la Semana 1 | |
| Diseño mobile-first verificado | Layout se reacomoda al achicar la ventana del navegador en vivo, sin recargar | |
Al menos un breakpoint md: o sm: real | Visible en el código fuente del header o de la grilla de proyectos | |
Estados focus: y hover: en el formulario | Aro de foco visible con Tab; color cambia al pasar el mouse por "Enviar" | |
| Redeploy automático confirmado | Un git push nuevo dispara un deploy visible en el dashboard de Render | |
| Auditoría Lighthouse con Accessibility ≥ 90 | Captura de pantalla del reporte, o corrida en vivo sobre la URL pública | |
| README con los dos enlaces de entrega | URL de Render + URL del repo, como texto pegable, no como imagen |
Reto de Live Coding (40%)
El docente elige uno de estos retos al azar y lo resuelves en vivo, sobre tu propio código, sin ayuda de IA.
# Reto 1: agregar una sección semántica nueva
"Agrega una sección <section id="testimonios"> con un <article> adentro,
enlázala desde el <nav>, y haz que sea responsiva con grid-cols-1 md:grid-cols-2."
# Reto 2: cambiar un breakpoint en vivo
"Tu grilla de Skills usa md:grid-cols-3. Cámbiala a que pase a 3 columnas
recién en lg: (1024px) en vez de md: (768px), y explica qué se ve distinto
en una tablet mientras lo haces."
# Reto 3: corregir un hallazgo de accesibilidad en vivo
"Baja el puntaje de Accessibility de Lighthouse a propósito quitando un
atributo alt, corre la auditoría, y después arréglalo mientras explicas
por qué Lighthouse lo marcó."
No se espera memoria perfecta de sintaxis — se espera que sepas dónde buscar (tu propio código, la documentación de Tailwind) y que entiendas por qué tu solución funciona.
Examen conceptual rápido (25%)
Presencial, sin dispositivos. Preguntas cortas, de las que ya se explicaron en el paso 01 de cada guía semanal.
¿Qué diferencia hay entre <section> y <div>, y por qué un lector de pantalla los trata distinto?
¿Qué significa que Tailwind sea "utility-first" en comparación con escribir un archivo .css tradicional?
¿Qué quiere decir "mobile-first" y por qué una clase sin prefijo aplica primero al celular?
¿Qué diferencia hay entre required y type="email" como atributos de validación HTML5?
¿Qué comprueba Lighthouse en la categoría Accessibility, y por qué el contraste de color importa?
Rastreo de commits en GitHub (20%)
Se revisa el historial completo del repo, no solo el estado final.
Al menos 1 commit al cerrar la Semana 1 ("estructura semántica...") y otro al cerrar la Semana 2 ("rediseño responsivo con Tailwind..."), con mensajes que describen qué cambió.
Un único commit gigante la noche anterior a la entrega, o mensajes genéricos tipo "update" / "cambios".
Bandas de calificación
EXCELENTE · 9-10
Resuelve el reto de live coding sin ayuda, defiende cualquier línea de su HTML/Tailwind y explica el "por qué" de sus decisiones de diseño responsivo.
SUFICIENTE · 6-8
Resuelve el live coding con una pista puntual; defiende la mayoría de su código con dudas menores sobre algún breakpoint o clase específica.
INSUFICIENTE · 0-5
No puede modificar su propio HTML/Tailwind en vivo, o el sitio de Render no responde al momento de la revisión.
Evidencia mínima a tener lista antes de tu turno
- URL de Render abierta y probada (recarga forzada
Ctrl+F5antes de entrar) - Repo de GitHub abierto en la pestaña de commits
- VS Code abierto con tu proyecto, listo para el reto de live coding
- Captura del reporte de Lighthouse a mano
Django + MySQL en la nube
Semanas 3-4 · Modelos, migraciones y despliegue dinámicoMisma Matriz Anti-IA, ahora aplicada a lo construido en las guías de la Semana 3 y la Semana 4: el proyecto Django conectado a MySQL en Aiven y publicado como Web Service en Render.
Ponderación de la Unidad
Los mismos cuatro componentes, con ejemplos concretos de Django, MySQL y Render.
3-5 min: modificar el modelo o una vista en vivo y migrar (ver 2.3).
Flujo HTTP request/response, arquitectura MTV, ORM vs. SQL puro (ver 2.4).
Progresión Semana 3 → Semana 4 visible en el historial (ver 2.5).
El Web Service de Render debe responder y /admin debe funcionar (ver checklist 2.2).
Lista de cotejo funcional (15% "Entregable publicado")
El docente lo verifica abriendo tu Web Service de Render, tu panel /admin y tu repo de GitHub en vivo.
| ✓ | Ítem a verificar | Cómo se verifica |
|---|---|---|
| Entorno virtual y dependencias documentadas | requirements.txt presente y actualizado en el repo | |
.env.example en el repo, .env NO en el repo | .gitignore incluye .env; se revisa el listado de archivos en GitHub | |
| Conexión a MySQL real (Aiven), no SQLite | DATABASES['default']['ENGINE'] es django.db.backends.mysql | |
Modelo Servicio definido con campos correctos | FK a User, título, descripción, precio, categoría, fecha — visibles en models.py | |
| Migraciones aplicadas sin errores | Archivo 0001_initial.py en core/migrations/, subido al repo | |
Modelo registrado en admin.py | "Servicio" visible como modelo administrable en /admin | |
Web Service desplegado en Render, estado Live | URL https://...onrender.com responde en el momento de la revisión | |
DEBUG=False en producción | Una URL inexistente muestra un error genérico, no el traceback de Django | |
SECRET_KEY y credenciales fuera del código | No aparecen valores reales hardcodeados en settings.py en GitHub | |
Panel /admin accesible en producción | Login funcional con el superusuario (creado desde la computadora con createsuperuser; es la misma base de Aiven que usa Render) | |
| Al menos 5 registros reales cargados | Visibles tanto en /admin como en la vista pública /servicios/ | |
| Misma base de datos en local y en producción | Un registro cargado en Render aparece también al correr runserver en local |
Reto de Live Coding (40%)
El reto sugerido explícitamente para el cierre de esta Unidad: agregar un campo al modelo y migrar en vivo, sin romper los datos existentes.
# Reto 1 (el sugerido en la guía de Semana 4): agregar un campo y migrar en vivo
"Agrega el campo 'disponible = models.BooleanField(default=True)' al modelo
Servicio, corre makemigrations y migrate en vivo, y muestra que los 5
registros que ya tenías siguen intactos después de migrar."
# Reto 2: modificar una vista en vivo
"La vista servicios() muestra todos los registros sin ordenar. Agrega
.order_by('-creado_en') a la consulta y explica qué SQL genera Django
por detrás."
# Reto 3: diagnosticar un problema de configuración
"Te muestro un settings.py con ALLOWED_HOSTS vacío en producción.
Explica qué error va a tirar Django y corrígelo en vivo."
Practica el reto sugerido (agregar un campo y migrar) al menos una vez antes de tu turno — es el que aparece explícitamente como evidencia a defender en el cierre de esta Unidad.
Examen conceptual rápido (25%)
Mismas tres ideas que menciona la Matriz Anti-IA del curso para esta Unidad: flujo HTTP, arquitectura MTV, ORM vs. SQL.
Recorre el flujo completo de una petición: desde que el navegador pide una URL hasta que Django devuelve el HTML final.
¿Qué responsabilidad tiene el Model, cuál la View y cuál el Template? Da un ejemplo con tu propio Servicio.
¿Qué ventaja tiene escribir Servicio.objects.all() en vez de un SELECT * FROM core_servicio a mano?
¿Por qué makemigrations y migrate son dos comandos separados y no uno solo?
¿Qué pasaría si subieras tu archivo .env real a un repositorio público de GitHub?
Rastreo de commits en GitHub (20%)
Se espera ver la progresión técnica de la Unidad reflejada en mensajes de commit, no solo en el código final.
Mensajes como "Conectar Django a MySQL en Aiven", "Agregar modelo Servicio y migraciones", "Preparar proyecto para producción" — cada uno corresponde a un paso real de la guía.
Un commit único que ya incluye modelo, migraciones y configuración de producción junto — sin poder explicar en qué orden se hizo cada cosa.
Bandas de calificación
EXCELENTE · 9-10
Agrega el campo y migra en vivo sin ayuda; explica con claridad el flujo MTV y por qué la configuración usa variables de entorno.
SUFICIENTE · 6-8
Logra migrar en vivo con una pista; explica el flujo MTV en general pero duda en algún detalle del ORM.
INSUFICIENTE · 0-5
No puede modificar el modelo en vivo, o /admin no responde en producción al momento de la revisión.
Evidencia mínima a tener lista antes de tu turno
- URL del Web Service de Render abierta y probada
/adminabierto con sesión iniciada, mostrando al menos 5 registros deServicio- VS Code abierto con
models.py,views.pyysettings.pya mano - Terminal local lista para correr
makemigrations/migrateen vivo
CRUD Dinámico y Sesiones
Semanas 5-6 · ModelForms, autenticación y aislamiento de datos por usuarioMisma Matriz Anti-IA, ahora aplicada a lo construido en las guías de la Semana 5 y la Semana 6: el CRUD completo de Servicio con formularios propios, y el sistema de registro/login/logout que aísla los datos de cada usuario.
Ponderación de la Unidad
Los mismos cuatro componentes, con ejemplos concretos de ModelForms, sesiones y control de acceso.
3-5 min: crear un usuario nuevo y demostrar en vivo que no ve los datos de otro (ver 3.3).
ModelForm, CSRF, sesiones, hashing de contraseñas y control de acceso (ver 3.4).
Progresión Semana 5 → Semana 6 visible en el historial (ver 3.5).
CRUD + login deben funcionar en producción, con datos aislados por usuario (ver checklist 3.2).
Lista de cotejo funcional (15% "Entregable publicado")
El docente lo verifica abriendo tu URL de producción con dos cuentas de usuario distintas.
| ✓ | Ítem a verificar | Cómo se verifica |
|---|---|---|
ServicioForm (ModelForm) definido | Campos coinciden con el modelo; propietario queda fuera de fields | |
Crear, Editar y Eliminar funcionan sin usar /admin | Probado en vivo desde /servicios/ en producción | |
| Eliminar exige confirmación por POST | Un GET a la URL de eliminar solo muestra la pantalla "¿Seguro?", no borra nada | |
| Validación personalizada en al menos un campo | clean_<campo> visible en forms.py y mensaje de error visible en pantalla | |
| Registro y Login propios funcionando | /registro/ y /login/ responden en producción, sin depender de /admin | |
| Logout funcional con mensaje de confirmación | /logout/ cierra la sesión y muestra un mensaje flash | |
CRUD protegido con @login_required | Visitar /servicios/nuevo/ sin sesión redirige al login | |
| Listado filtrado por usuario dueño | Servicio.objects.filter(propietario=request.user) en views.py | |
| Editar/Eliminar de un registro ajeno devuelve 404 | Probado escribiendo a mano el id de un servicio de otra cuenta en la URL | |
| Checklist de seguridad confirmado en Render | DEBUG=False, SECRET_KEY propia de producción, ALLOWED_HOSTS exacto, HTTPS activo | |
.env nunca subido al repositorio | No aparece en el listado de archivos de GitHub ni en git log --all -- .env | |
| Prueba de aislamiento documentada en el README | Descripción de la prueba con 2 cuentas (usuario_a / usuario_b) y su resultado |
Reto de Live Coding (40%)
El reto sugerido explícitamente para el cierre de esta Unidad: crear un usuario nuevo y demostrar que no ve los datos de otro.
# Reto 1 (el sugerido en la guía de Semana 6): demostrar el aislamiento en vivo
"Registra una cuenta nueva ahora mismo, carga un servicio, cierra sesión,
entra con tu cuenta de siempre y muéstrame que no ves el servicio que
acabas de crear con la cuenta nueva."
# Reto 2: forzar el 404 de acceso ajeno
"Aquí tienes el id de un servicio que no es tuyo. Intenta editarlo desde
la URL a mano y explica, leyendo views.py, por qué te da 404 en vez de
mostrarte el formulario."
# Reto 3: agregar una validación personalizada en vivo
"Agrega una regla a ServicioForm que rechace títulos de menos de 5
caracteres, usando clean_titulo, y pruébala en el formulario."
Practica el reto sugerido (registrar una cuenta y demostrar el aislamiento) al menos una vez antes de tu turno — es el que aparece explícitamente como evidencia a defender en el cierre de esta Unidad.
Examen conceptual rápido (25%)
Preguntas cortas sobre formularios, sesiones y control de acceso, ya explicadas en el paso 01 de cada guía semanal.
¿Qué genera automáticamente un ModelForm a partir de un modelo, y qué seguiría teniendo que escribirse a mano?
¿Para qué sirve {% csrf_token %} y qué pasaría si un formulario POST no lo incluyera?
¿Cómo guarda Django una contraseña — se puede "desencriptar" para verla? Explica qué es el hashing.
¿Qué diferencia hay entre Servicio.objects.all() y Servicio.objects.filter(propietario=request.user)?
¿Qué es una referencia insegura a objetos (IDOR) y cómo la evita get_object_or_404(Servicio, pk=pk, propietario=request.user)?
Rastreo de commits en GitHub (20%)
Se espera ver primero el CRUD y después la autenticación, en ese orden, reflejado en el historial.
Mensajes como "CRUD completo de Servicio: crear, editar y eliminar con ModelForms", "Agregar validacion personalizada: precio debe ser mayor a 0", "Autenticacion propia, sesiones y aislamiento de datos por usuario" — cada uno corresponde a un paso real de la guía.
Un commit único que ya incluye CRUD, login y filtro por usuario juntos — sin poder explicar en qué orden se implementó cada parte.
Bandas de calificación
EXCELENTE · 9-10
Registra un usuario y demuestra el aislamiento sin ayuda; explica con claridad por qué el filtro por propietario evita accesos ajenos.
SUFICIENTE · 6-8
Logra demostrar el aislamiento con una pista; explica el CSRF y las sesiones en general pero duda en algún detalle del filtro por usuario.
INSUFICIENTE · 0-5
No puede registrar/loguear un usuario en vivo, o un usuario logueado puede ver/editar datos de otro en producción.
Evidencia mínima a tener lista antes de tu turno
- URL de producción abierta, con sesión cerrada (para mostrar el registro desde cero)
- Dos cuentas de prueba ya creadas (
usuario_a/usuario_b), cada una con datos propios - Un
idde un servicio ajeno anotado, listo para probar el 404 de acceso - VS Code abierto con
forms.py,views.pyyurls.pya mano