Antes de leer una línea más, abre la demo. Entra con pedro / pedro-pythonista-2026, busca una película, guárdala. Lo que acadas de usar lo vas a haber escrito tú. Línea a línea. Desde la primera variable.
pedro · contraseña pedro-pythonista-2026
Date dos minutos. Entra con pedro / pedro-pythonista-2026, busca una película, guárdala en favoritos, mira las recomendaciones. No te lo estamos contando: te lo estamos enseñando funcionando.
Ahora piensa una cosa: ese código lo vas a haber escrito tú. Cada ruta, cada consulta a la base de datos, cada token de login. Línea a línea. Sin copiar. Sin trucos.
El curso no te enseña Python "por si algún día lo necesitas". Te lleva de tu primera variable hasta esta app en un servidor real con su dominio. Lo que acabas de ver funcionando es exactamente adónde vas a llegar. Abajo tienes cada pieza y el módulo donde la montas tú.
Seis features reales. No lo que hacen técnicamente, sino para qué te sirven cuando las hayas construido tú.
El usuario escribe un título y la app le devuelve resultados reales: año, rating, director. Para que sepas conectar tu backend con cualquier servicio externo del mercado, que es exactamente lo que te piden en un trabajo real.
A consumir una API externa de cine (OMDB) desde Python con requests:
mandar la petición, controlar errores con raise_for_status() y parsear el JSON
que devuelve. Lo mismo que hace un backend real cuando habla con otro servicio.
# Buscar en una API real de películas
import requests
resp = requests.get("https://www.omdbapi.com/",
params={"s": titulo, "apikey": API_KEY})
resp.raise_for_status()
peliculas = resp.json()["Search"]
Módulo 9 · Consumir APIs con requests
Cada usuario marca sus películas y la app las recuerda entre sesiones. Vuelves mañana y siguen ahí. Para que entiendas de verdad cómo persisten los datos — el salto que separa un script de juguete de una app que se puede usar.
A modelar datos con Flask-SQLAlchemy y a escribir los endpoints que los guardan y los leen:
un POST para añadir, un GET para listar. Empiezas guardándolo en una
lista en memoria (Módulo 9) y acabas persistiéndolo en base de datos de verdad.
# Marcar una película como vista / favorita
@app.post("/api/usuarios/<int:uid>/vistas")
@jwt_required()
def marcar_vista(uid):
db.session.add(vista)
db.session.commit()
return jsonify(vista), 201
Módulos 8 y 9 · SQLAlchemy + endpoints
Pedro guarda que le va el thriller; Ana, el drama. La app guarda los géneros favoritos de cada uno y los usa para personalizar lo que ve. Para que sepas proteger datos por usuario y entiendas por qué un endpoint sin proteger es un agujero de seguridad.
A relacionar datos en la base de datos (un usuario, sus géneros) y a proteger esos endpoints con ownership: solo tú puedes cambiar tus propios géneros. Aquí ves de verdad por qué un endpoint sin proteger es un agujero de seguridad.
@app.post("/api/usuarios/<int:uid>/generos-favoritos")
@jwt_required()
def elegir_generos(uid):
# Solo el propio usuario puede cambiarlos
if usuario_actual["user_id"] != uid:
return jsonify(error), 403
Módulos 8 y 9 · Modelos + ownership
Registro, login y sesiones con el estándar de la industria. El usuario pedro
con el que entraste en la demo es exactamente esto. Para que puedas enseñar en una entrevista
que sabes hacer autenticación real, no de tutorial.
A hacer autenticación de verdad con JWT, el estándar de la industria: hashear contraseñas
(nunca en texto plano), emitir un token al hacer login y proteger rutas con
@jwt_required(). Incluso roles (usuario normal vs. admin).
# Login: contraseña cifrada → token JWT
if check_password_hash(usuario.hash, contrasena):
token = create_access_token(identity=usuario.id)
return jsonify(access_token=token), 200
Módulo 9 · Autenticación JWT
La app no muestra un catálogo plano: sugiere películas según lo que has visto y los géneros que te gustan. Para que tengas en tu GitHub una feature de personalización que no tiene el 95% de los portfolios de programadores junior.
A montar un sistema de recomendaciones: cruzar los géneros favoritos del usuario con el catálogo, filtrar y ordenar resultados. Lo trabajas como reto integrador que junta base de datos, usuarios y lógica de negocio: una feature que te pedirían en un trabajo real de backend.
# Sugerencias según tus géneros favoritos
def recomendar(usuario):
return [p for p in catalogo
if p.genero in usuario.generos_favoritos
and p not in usuario.vistas]
Módulo 5 (POO con sets y polimorfismo) · reforzado como reto integrador en el Módulo 10.5
La app compara tus gustos con los de otros usuarios y calcula cuánto coincidís. "Tú y Pedro tenéis un 80% de afinidad": calculado por tu código. Para que en una entrevista puedas explicar cómo funciona un sistema colaborativo, porque es la base de Spotify, Netflix y cualquier app que te recomienda algo.
A comparar conjuntos de datos entre usuarios (géneros y películas en común) y a convertir eso en una puntuación. Es la base de cualquier sistema "a quién se parece más" que has visto en apps grandes, montado en pequeño y de verdad.
# Afinidad = gustos en común / gustos totales
def afinidad(a, b):
comunes = set(a.favoritos) & set(b.favoritos)
total = set(a.favoritos) | set(b.favoritos)
return len(comunes) / len(total)
Módulo 5 — Usuario.afinidad() con índice Jaccard (sets)
Nadie escribe una API con login el primer día. Se llega por capas. Esta es la progresión real: la misma app, creciendo módulo a módulo, hasta lo que acabas de probar en la demo. No hay saltos de fe. Cada versión funciona antes de pasar a la siguiente.
Variables, input(), listas y funciones. La app pide un título y un rating y los gestiona en memoria. Fea, pero ya funciona.
Archivos JSON, SQLite, clases y excepciones. Los datos ya no se pierden al cerrar y el código deja de ser un script para ser algo mantenible.
Flask, rutas, JSON y Flask-SQLAlchemy. La app se convierte en una API REST con CRUD completo y base de datos. Ya la puede consumir un navegador o un móvil.
Búsqueda con la API de OMDB, registro y login con JWT, ownership por usuario y tests con pytest. Cada uno tiene sus favoritos y sus géneros, protegidos. Esto ya es la app de la demo.
Git y GitHub, configuración por entorno, Gunicorn + Nginx y SSL en un VPS. Tu app deja tu portátil y vive en un dominio real, accesible 24/7. Justo como movietracker.elpythonista.com.
"Sé Python" no convence a nadie porque todo el mundo lo dice. Lo que convence es abrir un enlace delante del que te entrevista, hacer login en vivo y decir:
No es teoría. Es una URL que ya funciona, un repositorio que se puede leer y un proyecto que demuestra lo que sabes hacer. Sin pedir que te crean. Ya lo han visto.
Has abierto la demo. Has visto cada pieza y el módulo donde se monta. Solo queda un paso: pulsa el botón, accede hoy y escribe tu primera línea. La app que acabas de usar te espera al otro lado.
Sin suscripción. Sin cargos ocultos. Acceso de por vida.
Si en 14 días no es lo que esperabas, te devuelvo el dinero sin preguntas.