4 · Formularios HTML y plantillas Jinja
El JSON es para máquinas; los humanos necesitan una página. Un `<form method="post">` de HTML recoge valores de características y los envía por POST a una ruta, que renderiza una página de resultado con Jinja — un motor de plantillas que rellena marcadores `{{ ... }}` con tus valores de predicción en el servidor antes de enviar HTML terminado al navegador.
Para servir a humanos, un `<form method="post">` de HTML recoge campos y los envía por POST a una ruta; la ruta lee `request.form`, predice, y RENDERIZA una página de resultado con Jinja — un motor de plantillas que, EN EL SERVIDOR, sustituye marcadores `{{ valor }}` con datos reales y envía HTML terminado. Jinja automatiza la misma idea de rellenar-los-huecos que puedes hacer a mano con `str.format`.
Sin esto:
Sin un formulario + plantilla, un usuario no técnico no tiene forma de darle valores al modelo ni de leer una predicción — se quedaría mirando JSON crudo.
La API JSON de la lección 3 es perfecta para máquinas — pero un vendedor no va a usar curl. Los humanos necesitan una página web: un formulario donde escribir valores y un resultado legible. Flask sirve eso con formularios HTML y plantillas Jinja.
El formulario HTML envía la entrada. Un <form method="post" action="/predict-form"> envuelve un conjunto de campos <input>, cada uno con un name. Cuando el usuario hace clic en enviar, el navegador empaqueta los campos en una petición POST y los manda a la URL del action. Como es un formulario (no JSON), los valores llegan en request.form — request.form["tenure"] da el valor que el usuario escribió. (El mismo ciclo de antes; solo un formato de cuerpo distinto.)
La ruta maneja tanto mostrar el formulario como procesarlo. Un patrón común: un GET a la ruta muestra el formulario vacío; un POST a la misma ruta lee request.form, corre la predicción, y muestra el resultado. Te ramificas según request.method.
Jinja renderiza el resultado en HTML. Aquí está la pieza nueva. No construyes HTML pegando strings — escribes una plantilla: HTML con {{ marcadores }} y {% lógica %}, y Jinja los rellena en el servidor con los valores que le pasas. render_template_string("<p>Resultado: {{ label }}</p>", label="churn") produce <p>Resultado: churn</p>. Las dos construcciones centrales de Jinja:
{{ expresión }}— imprime un valor en el HTML (p. ej.{{ probability }}).{% sentencia %}— lógica:{% if churn %}...{% endif %},{% for row in rows %}...{% endfor %}.
Crucialmente, Jinja corre en el servidor: para cuando la respuesta llega al navegador, cada {{ }} ya está reemplazado con texto real. El navegador solo ve HTML terminado — nunca ve una plantilla. (En proyectos reales las plantillas viven en templates/*.html renderizadas con render_template("result.html", ...); render_template_string incrusta la plantilla para un ejemplo autocontenido.)
Extra: Jinja auto-escapa. Cuando imprimes texto provisto por el usuario con {{ }}, Jinja lo escapa para HTML por defecto, así que un <script> malicioso en la entrada se vuelve texto inofensivo en lugar de ejecutarse — una defensa integrada contra inyección que tendrías que recordar tú solo con formateo manual de strings.
La celda de solo-lectura muestra una ruta de formulario más una plantilla de resultado Jinja dentro de render_template_string. La celda ejecutable de abajo le quita Jinja para revelar la idea central: una plantilla es solo texto con huecos, y renderizar es rellenar los huecos con valores — exactamente lo que Jinja automatiza, mostrado aquí con str.format simple.
Una ruta de Flask que sirve un `<form method="post">` de HTML y una plantilla de resultado Jinja vía `render_template_string` — los marcadores `{{ }}` se rellenan en el servidor, y `request.form` lee los campos enviados.
Python (in browser)
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
¿Qué hace un motor de plantillas Jinja en el servidor cuando una ruta de Flask renderiza una página de resultado?
- Un `<form method="post">` de HTML recoge campos con nombre y los envía por POST a una ruta, donde Flask los lee de `request.form` (no de `request.get_json()`).
- Jinja renderiza plantillas en el servidor: `{{ valor }}` imprime un valor, `{% lógica %}` ejecuta control de flujo, y el navegador solo recibe HTML terminado.
- Una plantilla es texto con huecos y renderizar rellena los huecos — la misma idea que puedes hacer con `str.format`, que Jinja automatiza (y auto-escapa por seguridad).
Cualquier app de modelo con una página de cara al humano — una herramienta interna de scoring, un demo para interesados — usa un formulario para recoger características y una plantilla para renderizar la predicción.
Si lo quitas: Sin formularios ni plantillas el modelo es solo-JSON, usable por otros programas pero invisible para las personas no técnicas que a menudo necesitan ver sus predicciones.