Propuesta 2.0 · Formato Intensivo · 8 Semanas · 4 Unidades · 100% Gratuito

De HTML estático a una app Django + MySQL publicada en la nube, unidad por unidad.

Rediseño de "Aplicaciones Web" (75 hrs: 32 saber + 43 saber hacer) bajo el método Aprende → Publica → Defiende: mismo esquema de 4 Unidades + Anexos del temario oficial, pero cada Unidad entrega una URL en vivo sobre el mismo proyecto integrador.

Duración
8 semanas
Unidades
4 + Anexos
Horas totales
75 hrs
Costo hosting
$0 MXN

Core tecnológico obligatorio — sin PHP, sin XAMPP

HTML5 semántico Tailwind CSS Django (Python) MySQL en la nube Render (PaaS gratis) Git + GitHub VS Code + venv

Índice general del curso

Filosofía pedagógica

El método más efectivo para un curso intensivo: Aprende → Publica → Defiende

El error más común de las planeaciones tradicionales es enseñar todo el temario y publicar hasta el final. Aquí se invierte el orden: desde la Unidad 1 el alumno tiene una URL pública, y en cada Unidad esa misma URL evoluciona. Esto genera memoria muscular real, evidencia verificable y — clave contra el uso indebido de IA — la obligación de poder explicar en voz alta lo que esa URL hace.

1

Aprende (60 min)

Micro-explicación directa al grano: solo lo indispensable para producir el entregable de hoy. Nada de teoría sin destino inmediato.

2

Construye y Publica (180 min)

Práctica guiada paso a paso codificando junto al docente + los últimos 20-30 min siempre se usan para hacer git push y verificar que la URL en Render responde.

3

Defiende (1 hora autónoma)

Práctica autónoma monitoreada donde el alumno repite el cambio por su cuenta y se prepara para la defensa oral express de 3-5 min.

¿De dónde salen las 75 horas?

Saber — 32 hrs

4 horas de trabajo guiado × 8 semanas = 32 hrs de exposición directa, demostración en vivo y práctica dirigida con el docente, repartidas en las 4 Unidades (8 hrs por Unidad).

Saber hacer — 43 hrs

1 hora semanal de práctica autónoma supervisada (8 hrs) + 35 hrs distribuidas en tareas de refuerzo, avance del proyecto integrador fuera de clase y preparación de la defensa oral de cada Unidad.

Unidad 1 Semanas 1-2 · 8 hrs guiadas + 2 hrs autónomas

Front-End Esencial

Objetivo de la unidad: Construir y publicar un portafolio/landing con HTML5 semántico y Tailwind CSS responsivo, con su primer despliegue gratuito y funcional en Render.

Semana 1

Estructura semántica y primer despliegue en Render

Objetivo: Construir el esqueleto HTML5 semántico del portafolio personal y publicarlo como Static Site en Render con HTTPS.

Práctica guiada (4 hrs)

  • 0:00–0:45 · HTML5 semántico: header, nav, main, section, article, footer
  • 0:45–1:15 · Instalación VS Code + extensión Live Server + Git init
  • 1:15–2:45 · Maquetado guiado del portafolio (header + sobre mí + skills + contacto)
  • 2:45–3:15 · Crear repo en GitHub y primer git push
  • 3:15–4:00 · Alta de cuenta Render (sin tarjeta) + Static Site conectado al repo

Entregable publicado

https://<usuario>-portafolio.onrender.com

Portafolio HTML puro, sin estilos aún, con las 4 secciones semánticas visibles y accesibles por teclado.

Práctica autónoma (1 hr)

Agregar un formulario de contacto (sin backend aún) usando etiquetas <form>, <label> y atributos de validación HTML5.

Semana 2

Tailwind CSS responsivo y portafolio terminado

Objetivo: Aplicar Tailwind CSS vía CDN para lograr un diseño 100% responsivo (mobile-first) y redeployar la versión final.

Práctica guiada (4 hrs)

  • 0:00–0:40 · Utility-first CSS: por qué Tailwind y cómo leer clases
  • 0:40–1:10 · Configurar el CDN de Tailwind y probar el breakpoint md:
  • 1:10–3:00 · Rediseño guiado: grid/flex responsivo, tipografía, botones, tarjetas de proyectos
  • 3:00–3:40 · Formulario de contacto estilizado + estados focus: y hover:
  • 3:40–4:00 · Commit + push + verificación del redeploy automático en Render

Entregable publicado

Misma URL de la semana 1, actualizada

Landing/portafolio responsivo (probado en móvil y escritorio) con Lighthouse ≥ 90 en accesibilidad.

Práctica autónoma (1 hr)

Auditoría con Lighthouse/DevTools y corrección de al menos 2 hallazgos de accesibilidad o rendimiento.

Cierre de Unidad 1 — evidencia a defender

URL pública funcional + repo GitHub con al menos 2 commits fechados. Se evalúa con la Matriz Anti-IA (ver Anexos).

Unidad 2 Semanas 3-4 · 8 hrs guiadas + 2 hrs autónomas

Fundamentos de Django + Integración de MySQL en la nube

Objetivo de la unidad: Instalar Django, modelar datos y conectar el proyecto a una base de datos MySQL gestionada en la nube, culminando con el primer despliegue dinámico en Render. Para la guía completa de configuración ver Anexos → Guía de Hosting.

Semana 3

Primer proyecto Django y conexión a MySQL remoto

Objetivo: Instalar Django en un entorno virtual, crear la primera app y conectar settings.py a una base de datos MySQL gratuita en la nube (Aiven).

Práctica guiada (4 hrs)

  • 0:00–0:40 · Arquitectura MTV de Django vs. el mito "Django = PHP con esteroides"
  • 0:40–1:20 · python -m venv venv, pip install django pymysql, django-admin startproject
  • 1:20–2:00 · Crear cuenta Aiven for MySQL (free tier) y obtener host/puerto/usuario/password
  • 2:00–3:00 · Configurar DATABASES con variables de entorno + python manage.py migrate contra MySQL real
  • 3:00–4:00 · Primera vista function-based + ruta + plantilla DTL renderizando "Hola desde MySQL"

Entregable publicado

Repo GitHub con .env.example

Captura de migrate exitoso + captura de las tablas creadas en el panel de Aiven, subidas al repo como evidencia.

Práctica autónoma (1 hr)

Crear una segunda vista + ruta + plantilla que muestre datos estáticos en una tabla HTML con Tailwind.

Semana 4

Modelos, migraciones y primer despliegue dinámico en Render

Objetivo: Definir modelos del proyecto integrador, migrarlos a MySQL y publicar la primera versión dinámica en Render como Web Service.

Práctica guiada (4 hrs)

  • 0:00–0:40 · ORM de Django: de la clase Python a la tabla SQL
  • 0:40–1:40 · Diseño guiado del/los modelo(s) del proyecto integrador (campos, tipos, relaciones)
  • 1:40–2:15 · makemigrations / migrate + registro en admin.py
  • 2:15–3:15 · requirements.txt, gunicorn, Start Command y variables de entorno en Render
  • 3:15–4:00 · Deploy del Web Service en Render + migrate en vivo desde la Shell de Render

Entregable publicado

https://<proyecto>.onrender.com

App Django corriendo en Render, leyendo/escribiendo en la misma base MySQL usada localmente, con el panel /admin accesible.

Práctica autónoma (1 hr)

Dar de alta 5 registros reales desde /admin y verificar que aparecen en la vista pública.

Cierre de Unidad 2 — evidencia a defender

App dinámica en producción conectada a MySQL en la nube + capturas de migración. Live coding sugerido: "agrega un campo al modelo y migra en vivo".

Unidad 3 Semanas 5-6 · 8 hrs guiadas + 2 hrs autónomas

CRUD Dinámico y Sesiones

Objetivo de la unidad: Completar el ciclo Crear-Leer-Actualizar-Eliminar con formularios Django y proteger la aplicación con autenticación, sesiones y buenas prácticas de seguridad.

Semana 5

CRUD completo con ModelForms

Objetivo: Implementar Crear, Leer, Actualizar y Eliminar sobre el modelo principal usando formularios Django validados y Tailwind.

Práctica guiada (4 hrs)

  • 0:00–0:40 · ModelForm, {% csrf_token %} y ciclo petición/respuesta
  • 0:40–1:40 · Vista + template de "Crear" y "Listar" con Tailwind (tabla o tarjetas)
  • 1:40–2:40 · Vista + template de "Editar" reutilizando el mismo formulario
  • 2:40–3:20 · Vista de "Eliminar" con confirmación
  • 3:20–4:00 · Deploy y prueba end-to-end del CRUD ya en producción (Render + MySQL)

Entregable publicado

Misma URL de producción, actualizada

CRUD 100% funcional en vivo: se puede crear, editar y borrar un registro real desde el navegador sin usar /admin.

Práctica autónoma (1 hr)

Agregar validación personalizada a un campo del formulario (ej. longitud mínima o formato) y mostrar el mensaje de error con Tailwind.

Semana 6

Autenticación, sesiones y seguridad

Objetivo: Restringir el CRUD con login obligatorio, usar el sistema de autenticación de Django y asegurar la app (CSRF, hashing, variables de entorno).

Práctica guiada (4 hrs)

  • 0:00–0:40 · django.contrib.auth: usuarios, hashing de contraseñas y sesiones
  • 0:40–1:40 · Vistas de Registro y Login con formularios Tailwind
  • 1:40–2:20 · @login_required y Logout; mensajes de sesión
  • 2:20–3:10 · Relacionar registros con el usuario dueño (ForeignKey a User) — "cada quien ve/edita solo lo suyo"
  • 3:10–4:00 · Checklist de seguridad (DEBUG=False, SECRET_KEY en variable de entorno, ALLOWED_HOSTS) y deploy

Entregable publicado

Misma URL de producción, actualizada

Sistema con registro/login/logout funcionando en vivo; un usuario nuevo solo puede editar/borrar sus propios registros.

Práctica autónoma (1 hr)

Registrar 2 cuentas de prueba y documentar en el README cómo se comprobó el aislamiento de datos entre usuarios.

Cierre de Unidad 3 — evidencia a defender

CRUD + login funcionando en producción con datos aislados por usuario. Live coding sugerido: "crea un usuario nuevo y demuestra que no ve los datos de otro".

Unidad 4 Semanas 7-8 · 8 hrs guiadas + 2 hrs autónomas

Proyecto Integrador, Anti-IA Defense y Deployment Final

Objetivo de la unidad: Cerrar y pulir el proyecto integrador, congelar el despliegue final en Render + MySQL y sustentarlo mediante defensa oral en vivo. La calificación aplica la Matriz de Evaluación Anti-IA (ver Anexos).

Semana 7

Pulido funcional, UX y simulacro de defensa

Objetivo: Cerrar funcionalidades pendientes, mejorar UX/UI con Tailwind y realizar un simulacro completo de defensa oral y examen conceptual.

Práctica guiada (4 hrs)

  • 0:00–0:30 · Revisión grupal de bitácora de commits (¿hay evidencia de progreso real?)
  • 0:30–1:30 · Sesión de pulido: mensajes vacíos, paginación, búsqueda simple, estados vacíos ("aún no hay registros")
  • 1:30–2:30 · UI review por pares con checklist de accesibilidad y responsividad Tailwind
  • 2:30–3:20 · Simulacro de Live Coding (rol al azar: "agrega un campo al modelo y migra en vivo")
  • 3:20–4:00 · Examen conceptual rápido (flujo HTTP, ORM, arquitectura MTV)

Entregable publicado

Misma URL de producción, actualizada

Versión "feature-complete": todo el CRUD + login + UX pulida, sin errores 500 visibles.

Práctica autónoma (1 hr)

Preparar 2 minutos de "guion de defensa": qué hace el sistema, qué decisiones técnicas se tomaron y por qué.

Semana 8

Deployment final y defensa oral en vivo

Objetivo: Congelar y verificar el deployment final en Render + MySQL, y sustentar el proyecto completo frente al docente.

Práctica guiada (4 hrs)

  • 0:00–0:30 · Auditoría final: variables de entorno, backup del .sql, README actualizado
  • 0:30–1:00 · Última migración en producción y congelamiento de versión (tag/release en GitHub)
  • 1:00–3:30 · Defensa oral express por alumno (3-5 min): live coding + preguntas conceptuales
  • 3:30–4:00 · Retroalimentación grupal y cierre del curso

Entregable publicado

URL final + release en GitHub

Sistema completo, público, con login, CRUD y datos reales, defendido en vivo ante el docente.

Cierre

Portafolio final (ver Anexos → Plantilla) con los 8 enlaces publicados, listo para compartir en LinkedIn o con reclutadores.

Cierre de Unidad 4 — evidencia a defender

Proyecto integrador completo, público y defendido en vivo. Calificación final según la Matriz de Evaluación Anti-IA (Anexos).

Anexos Recursos transversales, válidos para las 4 Unidades

Material de apoyo del curso

Aquí vive todo lo que no pertenece a una sola Unidad porque se usa a lo largo de las 8 semanas: el proyecto integrador, la guía de hosting, la matriz de evaluación y la plantilla de portafolio.

Anexo A

Proyecto Integrador Unificado: "ImpulsaTec — Vitrina de Servicios"

En lugar de proyectos desechables por unidad, todo el curso construye una sola base de datos MySQL que crece Unidad por Unidad. Cada alumno crea su propia vitrina digital donde ofrece un servicio o producto real (tutorías, diseño, repostería, freelance, lo que sea) — práctico, motivante y reutilizable como portafolio de empleabilidad al terminar el curso.

Unidad 1

Vitrina estática

Landing HTML+Tailwind: quién soy, qué ofrezco, cómo contactarme.

Unidad 2

Catálogo dinámico

Modelo Servicio en MySQL: los productos/servicios ya viven en la base de datos, no en el HTML.

Unidad 3

Panel privado

CRUD + login: el dueño de la vitrina administra su catálogo desde una sesión autenticada.

Unidad 4

Producto final

Pulido, seguridad y publicación definitiva; se defiende como un producto real, no como una tarea.

Modelo mínimo sugerido (crece libremente por alumno):

# catalogo/models.py
# Comentario de ubicación: este código vive en el archivo models.py de la app "catalogo"

from django.db import models
# Traemos las herramientas de Django para describir tablas como clases de Python

from django.contrib.auth.models import User
# Traemos el modelo de usuario que Django ya trae incluido (login, contraseñas, sesiones)

class Servicio(models.Model):
    # Cada clase que hereda de models.Model se convierte en una TABLA dentro de MySQL

    propietario = models.ForeignKey(User, on_delete=models.CASCADE)
    # Relaciona este servicio con el usuario dueño; on_delete=CASCADE = si se borra el usuario, se borran sus servicios

    titulo = models.CharField(max_length=120)
    # Texto corto (máximo 120 caracteres), obligatorio

    descripcion = models.TextField()
    # Texto largo, sin límite fijo de caracteres

    precio = models.DecimalField(max_digits=8, decimal_places=2)
    # Número decimal: hasta 8 dígitos en total y 2 después del punto (ej. 1500.00)

    categoria = models.CharField(max_length=60)
    # Texto corto para clasificar el servicio (ej. "Tutorías", "Diseño")

    creado_en = models.DateTimeField(auto_now_add=True)
    # auto_now_add = Django guarda automáticamente la fecha y hora cuando se crea el registro

    def __str__(self):
        # Define qué texto se muestra cuando Django necesita "imprimir" este objeto (ej. en el panel /admin)
        return self.titulo
        # Mostrará el título en vez de algo genérico como "Servicio object (1)"

Anexo B

Guía rápida: Render + MySQL en la nube

Se configura una sola vez al inicio de la Unidad 2 y queda lista para publicar avances cada semana con un simple git push.

  1. 1

    Crear la base de datos MySQL gratuita (Aiven)

    Ir a aiven.io → crear cuenta con GitHub/Google → "Create service" → MySQL → plan gratuito (Free Plan) → región cercana → nombrar el servicio.

    Copiar del panel: Host, Port, User, Password y Database name.

  2. 2

    Conectar Django localmente

    pip install pymysql python-decouple, luego en settings.py:

    import pymysql
    # Traemos el conector que traduce entre Django y MySQL
    
    pymysql.install_as_MySQLdb()
    # Hace que Django use pymysql como si fuera el driver oficial de MySQL
    
    from decouple import config
    # Función para leer variables secretas desde el archivo .env
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',        # Motor de base de datos: MySQL
            'NAME': config('DB_NAME'),                     # Nombre de la base de datos, leído del .env
            'USER': config('DB_USER'),                     # Usuario de conexión, leído del .env
            'PASSWORD': config('DB_PASSWORD'),             # Contraseña de conexión, leída del .env
            'HOST': config('DB_HOST'),                     # Servidor donde vive la base de datos, leído del .env
            'PORT': config('DB_PORT', default='3306'),     # Puerto de conexión; si no existe en .env, usa 3306 por defecto
            'OPTIONS': {'ssl': {'ssl-mode': 'REQUIRED'}},  # Aiven exige que la conexión venga cifrada (SSL)
        }
    }

    Crear un archivo .env local (nunca subirlo a GitHub, agregar a .gitignore) con esas 5 variables.

  3. 3

    Migrar y probar en local

    python manage.py migrate
    # Crea en tu base de datos MySQL las tablas que Django necesita internamente (usuarios, sesiones, permisos, etc.)
    
    python manage.py createsuperuser
    # Crea tu usuario administrador: te pedirá usuario, correo y contraseña
    
    python manage.py runserver
    # Levanta el servidor local; abre http://127.0.0.1:8000/ en tu navegador
  4. 4

    Preparar el proyecto para producción

    Instalar gunicorn y whitenoise; generar requirements.txt:

    pip install gunicorn whitenoise
    # gunicorn = servidor que corre Django en Render (runserver es solo para tu computadora)
    # whitenoise = permite servir tus archivos CSS/imágenes sin configuración extra
    
    pip freeze > requirements.txt
    # Genera una lista con todo lo que instalaste; Render la usa para instalar lo mismo en la nube
    
    git add . && git commit -m "listo para deploy" && git push
    # git add . = marca todos los archivos modificados como "listos para guardar" (staging)
    # && = "y luego, si lo anterior no falló, ejecuta lo siguiente"
    # git commit -m "..." = guarda una "fotografía" de esos archivos con un mensaje que describe el cambio
    # git push = sube esos commits guardados en tu computadora hacia GitHub
  5. 5

    Crear el Web Service en Render

    render.com → registrarse con GitHub → "New +" → "Web Service" → seleccionar el repositorio.

    • Build Command: pip install -r requirements.txt && python manage.py collectstatic --noinput
    • Start Command: gunicorn miproyecto.wsgi
    • Plan: Free
  6. 6

    Configurar variables de entorno en Render

    En "Environment" agregar las mismas 5 variables del .env local, más:

    SECRET_KEY=
    # Clave secreta de Django; genera una distinta y larga solo para producción, nunca la reutilices del .env local
    
    DEBUG=False
    # En producción SIEMPRE False: oculta detalles técnicos de errores a cualquier visitante
    
    ALLOWED_HOSTS=.onrender.com
    # Le dice a Django "solo acepta peticiones que lleguen a este dominio exacto"
  7. 7

    Deploy y migración en la nube

    Render construye y despliega automáticamente. Luego, desde la pestaña Shell del servicio en Render:

    python manage.py migrate
    # Crea las tablas en MySQL, esta vez desde el servidor de Render (misma base de datos de Aiven)
    
    python manage.py createsuperuser
    # Crea tu usuario administrador ya en producción

    Listo: la URL https://<proyecto>.onrender.com queda pública con HTTPS. Cada git push a partir de aquí redeploya automáticamente.

Alternativa equivalente: Railway (voucher inicial gratuito) o TiDB Cloud Serverless funcionan igual de bien como base MySQL gestionada; el flujo de variables de entorno es el mismo. Se recomienda fijar un solo proveedor por grupo para simplificar el soporte en clase.

Anexo C

Matriz de Evaluación Anti-IA

El código estático entregado vale 0% si el alumno no puede defenderlo. La calificación de cada Unidad combina cuatro fuentes independientes de evidencia.

Componente Peso Cómo se aplica Señal de alerta (posible IA sin comprensión)
Live Coding / Defensa oral express 40% 3-5 min por alumno, al cierre de cada Unidad: "modifica esta vista", "agrega una columna al modelo y migra en vivo", "explica qué pasa si quito @login_required". No puede modificar su propio código sin ayuda; no reconoce nombres de sus propias variables/vistas.
Examen conceptual rápido 25% Presencial, sin dispositivos, uno por Unidad: flujo HTTP request/response, arquitectura MTV, diferencia ORM vs. SQL puro. Domina el código pero no puede describir el flujo general del framework.
Rastreo de commits en GitHub 20% Se revisa el historial semanal: frecuencia, mensajes descriptivos, progresión incremental coherente con el cronograma de cada Unidad. Un solo commit gigante la noche anterior a la entrega; mensajes genéricos tipo "update".
Entregable funcional publicado 15% La URL de Render debe responder en el momento de la revisión y cumplir el checklist funcional de la Unidad. Funciona en local pero nunca se publicó, o el deploy fue hecho por alguien más.

Excelente (9-10)

Defiende cualquier línea de su código, resuelve el reto de live coding sin ayuda y explica el "por qué" de sus decisiones.

Suficiente (6-8)

Defiende la mayoría de su código con pequeñas dudas puntuales; resuelve el live coding con una pista.

Insuficiente (0-5)

No puede modificar su propio código en vivo; el entregable no está publicado o no coincide con lo defendido.

Anexo D

Plantilla de Portafolio Personalizable

Cada alumno descarga plantilla-portafolio.html, sustituye sus datos y va agregando el enlace de su entregable al cerrar cada Unidad. Es el mismo archivo que se publica como portafolio final en la Unidad 4.

Vista previa del código (fragmento editable)

<!-- ======= EDITA SOLO ESTA SECCIÓN ======= -->
<!-- Esta línea es un comentario HTML: el navegador la ignora, solo sirve de aviso para quien edita el archivo -->

<section id="datos-alumno">
<!-- <section> = agrupa un bloque temático de contenido; id="datos-alumno" permite ubicarlo o enlazarlo desde otro lugar -->

  <h1>[NOMBRE COMPLETO DEL ALUMNO]</h1>
  <!-- <h1> = título principal de la página; reemplaza el texto entre corchetes por tu nombre real -->

  <p>Matrícula: [MATRÍCULA] · Grupo: [GRUPO]</p>
  <!-- <p> = párrafo de texto normal; aquí van dos datos juntos, separados por el símbolo · -->
</section>

<!-- ======= EDITA LOS ENLACES POR UNIDAD ======= -->

<li><a href="[URL-UNIDAD-1]">Unidad 1 · Portafolio estático</a></li>
<!-- <li> = un elemento de lista · <a href="..."> = enlace clicable; reemplaza [URL-UNIDAD-1] por tu URL real de Render -->

<li><a href="[URL-UNIDAD-2]">Unidad 2 · App Django + MySQL en Render</a></li>
<!-- Mismo patrón: el texto entre <a> y </a> es lo que ve el visitante; href="..." es a dónde lo lleva el clic -->

<li><a href="[URL-UNIDAD-4]">Unidad 4 · Proyecto integrador final</a></li>
<!-- Repite este mismo patrón <li><a href="...">...</a></li> para agregar el enlace de la Unidad 3 -->