Solicitudes en FLASK (GET / POST) + Templates HTML

solicitudes en flaskSi ya has realizado al menos un “Hola mundo!” es momento de hablar de las solicitudes en flask. Como habíamos visto en el post anterior aprendimos a generar rutas en nuestro proyecto flask y como mostrar determinadas salidas dependiendo la que el usuario visite. En este caso debemos comprender una serie de diferencias entre las solicitudes que nuestro usuario le realiza al servidor y como responder ante ellas. Y luego aprenderemos a crear una carpeta “templates” y alojar allí nuestros archivos html para comenzar a darle forma a nuestro proyecto de un portfolio en flask.

-Seguro no esperabaís un post tan pronto. ¿Verdad?

 

¿Qué son las solicitudes en flask?

Normalmente quienes saben algo de aplicaciones cliente-servidor conocen el concepto de solicitud y respuesta. Pero para quienes no se trata de un esquema muy sencillo de comprender. Cada vez que tu visitas un sitio web, haces clic en un botón de un sitio o aplicación estás enviando una solicitud. La forma en que funcione este programa, aplicación o sitio web determinará que hace y donde se envía tu solicitud, porque así lo ha definido quien la programó, o bien alguna herramienta que utilizo el desarrollador!.

Supongamos entonces que tu realizas una simple búsqueda en google, cuando formulas una pregunta o colocas una palabra para conocer su definición estas realizando a google.com una solicitud con ciertos argumentos para determinados parámetros. En este caso google espera que tu ingreses una palabra o una cadena de texto para realizar una búsqueda. Pues esto que tu haces puede ser considerado una solicitud http. Que de forma “sencilla” podríamos verla algo así:

Solicitudes en flask

google peticiones en flaskAsí siempre que visites una web estás enviando una solicitud. Pero esta solicitud no es simplemente un “hey dame X cosa!”. Es una petición formal donde se envían datos con el fin de ser procesados y obtener una respuesta. Estos datos pueden ir desde información personal que tu no has consentido enviar, hasta los datos que tu has ingresado en un formulario por ejemplo u alguna imagen que has decidido subir a un servidor. Los servidores esperan determinadas solicitudes con determinados argumentos para los parámetros requeridos para procesar esa solicitud. Así como te decía de la búsqueda en google, este espera que tu ingreses al menos una letra, palabra o frase para poder comenzar a buscarla a través de la red.

solicitudes flask - error 404

Cuando un servidor recibe una solicitud devuelve al cliente un código que indica al navegador el resultado de dicha petición. Seguramente te habrá pasado de ingresar a algún sitio y obtener un famoso “Error 404: Not Found“. Pues 404 es un código que devuelve el servidor para indicar que la ruta o url que has seguido no existe o ha sido movida sin re-direccionamiento. Y por ende se produce un error. Al igual que cuando obtenemos un error del tipo 500 (Internal server error) y este si es un error que me da mucho miedo!.

Aquí puedes conocer los códigos de errores que bien pueden ser del cliente (Errores 4xx) o del servidor (Errores 5xx). Y es importante saberlo, para cuando recibas un error en tu aplicación flask por no procesar bien una petición.

Estructura de una solicitud http

Toda solicitud http que envía un navegador contiene determinada información organizada en determinada estructura. Y presta atención porque estos conocimientos te serán muy útiles a continuación:

Una solicitud que envía el navegador está compuesta de (entre otras):

  1. Una línea de inicio: A mi me gusta imaginar las peticiones como flechas, esas flechas tienen una punta, una cabeza. Esta es la que le indica al servidor que tipo de respuesta se espera. Cuando enviamos una PETICIÓN HTTP está puede ser GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONs, TRACE o PATCH. Y se trata de un método que indica que respuesta se espera el cliente del servidor para determinado recurso. Cuando tu cargas una pagina sencilla en html en  tu navegador por ejemplo Google Chrome estás enviando normalmente una petición GET (obtener datos del servidor), que podemos interpretar como “Obtener” o “Dame”.  Cuando tu rellenas un formulario y le das al clic de “Enviar” o “Submit” estas enviando una solicitud POST (enviar datos al servidor). Y estas dos son las que más nos interesan en este post.
  2. Una cabecera, donde también se incluye la linea de inicio (antes mencionada). Las cabeceras http contienen información del tipo de petición como te decía más arriba y también describen si esta petición tiene cuerpo y le brindan al servidor determinada información acerca del mismo.
  3. Linea en blanco, vacía o Empty Line: Esta linea indica simplemente toda la meta-información enviada.
  4. Y finalmente un cuerpo: El cuerpo de la petición contiene la información enviada por el cliente, que puede ir desde los datos de rellenado que ha colocado en un formulario, hasta archivos adjuntos entre otros.

Nosotros al programar una aplicación en flask debemos aprender a gestionar estas solicitudes y saber cuando se espera una u otra para evitar entre otras cosas errores y vulnerabilidades en el servidor.

¿Cómo gestionar las solicitudes en flask?

Primeramente vamos a comprender y utilizar el tipo de solicitud GET y seguidamente aprenderemos a procesar una solicitud POST en nuestro proyecto, tal como lo veníamos desarrollando incorporando un template en html para las vistas. Fíjate que hasta ahora en nuestro primer “Hola mundo!” en flask aún no le indiquemos el tipo de solicitud en nuestras rutas el servidor procesa la petición del cliente cuando accedemos en el navegador a nuestra aplicación. Esto es porque el servidor interpreta automáticamente que se trata de una solicitud GET donde se intenta obtener el contenido de esa página web.

Como sabes hemos estado del lado del servidor (programando nuestra app en Flask) y del lado del Cliente (cargando nuestra página en local desde nuestro navegador). Desde el lado del servidor podemos trabajar la solicitud que nuestra aplicación espera y desde el lado del cliente la que enviamos. Pero ¿como hacemos del lado del servidor para saber que solicitud se nos está enviando?

bases de datos tiendaSimplemente suponemos que nos envían una solicitud GET  y otorgamos el contenido para ser leído, porque recordemos GET refiere a una solicitud de respuesta o datos al servidor y en el caso de que el cliente haga una solicitud POST (envio de datos al servidor para que este los procese y otorgue una respuesta) debemos estar preparados para procesarla, en el caso que determinada ruta o url de nuestro sitio sea una en la que es necesario que el usuario nos envíe datos de entrada adicionales para procesarlos. Si yo solamente en mi servidor voy a mostrar un template y es una página informativa nada más, no necesito procesar ninguna petición POST, porque no espero ningún dato de entrada del usuario. Y permitir una solicitud POST donde no se procesa adecuadamente ni es necesaria representaría una posible VULNERABILIDAD o SOBRECARGA y podría ocasionarnos grandes disgustos. No te confundas claro, ambas solicitudes esperan una respuesta del servidor, ambas envían datos al servidor y por eso se suele cometer el error de novato de confundirlas o “utilizar una u otra, según se me venga en gana”. Lo cierto es que para solicitud de datos usamos GET, y para solicitud de cambios o procesamiento de datos usamos POST. Porque podemos usar cualquiera de las dos por ejemplo para un “LOGIN” pero si utilizáramos GET para enviar los datos del usuario, estos se mostrarían en la URL provocando una grave VULNERABILIDAD.

Así que habiendo comprendido esto vamos a aprender a gestionar estas solicitudes en nuestra rutas indicándolas como parámetros en el decorador de contexto, que vimos anteriormente nos indica que se trata de una ruta a continuación y es también que indica que cabeceras admite para esa ruta y como va a procesarlas.

 

Procesar una solicitud GET en FLASK

 

Ve a tu Visual Studio Code, activa tu entorno virtual y vamos a trabajar. Recordemos que teníamos lo siguiente:

Mi proyecto Flask - Solicitudes en Flask

Tenemos allí dos rutas, una con la función holamundo() que corresponde a la página de inicio (‘/’) y otra que corresponde a una página informativa donde vamos a mostrar nuestros proyectos por ejemplo. Y a la que accederíamos a través de la url (‘mis-proyectos/). Ahora vamos a especificar que ambas RUTAS o URL’S se corresponden a procesar una petición GET. Debido a que en ningún momento le vamos a solicitar ninguna información adicional al usuario!. Por lo que nos sería innecesario procesar una petición POST. Para ello añadimos en el decorador

@app.route(‘seguido de nuestra url’, methods = [‘GET’])

En routes podemos pasar diferentes parámetros en forma de variable, lista, diccionario, etc. En este caso las solicitudes admitidas se pasan en forma de lista. En el caso de tratarse de una solicitud GET simplemente se pasa GET, pero en el caso de una solicitud POST para un formulario por ejemplo se suelen pasar ambas como [‘GET’, ‘POST’] y se procesan por separado dentro de la función, en caso de ser GET la solicitud del cliente, mostrar el formulario y en caso de ser POST comprobar y procesar los datos enviados. De lo contrario si solo usáramos POST, no procesaria la solicitud GET por lo que no se mostraría ninguna página ni formulario. ¿Me explico?

Entonces nuestro archivo quedaría así:

#Importar
from flask import Flask

#Crear app medante instancia
app = Flask(__name__)

#Crear rutas con sus correspondientes funciones
@app.route('/', methods=['GET']) #Indicamos metodo GET
def holamundo():
    return 'Hola Mundo!'

@app.route('/mis-proyectos', methods=['GET'])
def mostrarproyectos():
    return 'Aquí se mostrarán mis proyectos'

#Ejecutar nuestra app cuando ejecutemos este archivo run.py

if __name__ == '__main__':
    app.run(debug=True)

Fíjate al ejecutar!

Solicitudes en Flask - Solicitud GET

Presta atención en lo siguiente, cuando ejecutamos el código y visitamos nuestro sitio web (127.0.0.1:5000) en la terminal se muestra la petición GET confirmada con código 200. Lo que significa que fue exitosa!. Y también se nos muestra un 404 al intentar obtener un favicon (el iconito ese superior que tienen todas las páginas web por defecto). Pero a eso, por ahora podemos restarle importancia..

hola mundo

Hasta aquí has aprendido mucho aunque no lo creas. Sabes lo que es una solicitud y como deberás procesarla según el contenido que ofrecerá determinada RUTA o URL de tu proyecto.

-Pero esto, así es una porquería. Solo se muestra un simple “Hola mundo!”, una cutrada. ¿Tanto leí para eso?

-Tranqui, ahí vamos a eso!

 

 

 

Devolver un template html tras una solicitud GET

Vamos a crear dentro de nuestra carpeta de proyecto otra carpeta llamada “templates” donde almacenaremos los templates (modelos de diseño) en html, lo he colocado en rojo porque estoy usando estos colores para que distingas cuando se trata de MODELO, CONTROLADOR o VISTA. Los archivos HTML corresponden a la parte  de la vista, a la que le vamos a servir al usuario.

Dentro de la carpeta que acabamos de crear vamos a crear un nuevo archivo llamado “index.html” (este nombre de archivo corresponde a la pagina principal de cualquier sitio web) y otro archivo llamado “contacto.html” (donde más adelante vamos a crear un formulario de contacto, para que nuestro cliente o usuario que visita la página pueda contactarnos vía mail.)

brujería-en-flask

En Visual Studio Code dentro de cada archivo escribe “html:5” y presiona enter. Observa la brujería!!. Si no estás usando VS Code será mejor que copies la plantilla a continuación. Lo que estás viendo es la estructura básica de un archivo HTML que a continuación voy a explicar breve-mente. Y no hagas commit aún que vamos a crear otra rama en un momento para comenzar a trabajar con templates.

Te dejo un videito cortito..


 

Ahora es momento de mostrar y explicar este código en html, lo siento para quienes ya lo saben. Tener que tragarse esto, pero bueno.. Tal vez hay alguno que jamas vió html en su vida, y por ahí se la salvamos!. La programación lo puede todo, a mi me va a sacar de la jodida pobreza, tenlo por seguro, sigue leyendo y nunca pierdas la fe en ti mismo. A darle caña:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
</html>
  1. Línea 1: Nos indica que se traba de un archivo HTML, como puedes ver html trabaja con etiquetas que consisten en palabras reservadas dentro de los símbolos de mayor y menor, o ranitas como decía un viejo profesor. Pero en esta caso luego de la apertura de la etiqueta “<” contiene un signo de interrogación, lo que expresa que es un comentario informativo. Esta información es muy importante para el navegador del cliente!
  2. La siguiente etiqueta es la que abre un archivo html, esta etiqueta indica que lo que viene a continuación es puro html, y como te dije HTML al trabajar con etiquetas siempre, pero siempre las etiquetas abiertas deben ser cerradas. Echa un vistazo a la ultima línea donde se cierra el archivo HTML!
  3. La etiqueta que sigue “head” indica que aquí se encuentra la información de la cabecera del archivo y es dentro de esta donde normalmente se incluye el título mediante la etiqueta “title” que actualmente es “Document” y otra información también relevante a mostrar en el navegador del cliente. En el caso de Chrome este título aparecerá arriba en la pestaña.
  4. Las que siguen se encuentran dentro del “head” (porque se cierra más debajo englobando otras etiquetas que abren y cierran dentro de este bloque.. Cada etiqueta que abre se considera un bloque y básicamente tenemos bloques dentro de bloques en un solo bloque gigante que abre  y cierra como HTML.) son etiquetas “meta“. Las etiquetas meta le envían información al cliente o navegador que abra este archivo. En este caso le indica la codificación de caracteres aceptados y añade compatibilidad con el navegador de Win “Microsoft Edge”.
  5. Finalmente cierra el bloque “head” y comienza el “body” en la línea siguiente, que refiere al cuerpo del archivo. Dentro del body se encuentra lo que se mostrará en el sitio web, divisorios, menús, barras laterales, texto, imágenes, etc.
  6. Con el “body” en blanco, porque esto es una plantilla automática generada por Visual Studio Code, finalmente cierra el “body” y finalmente cierra el bloque “html

Y así es como se estructura normalmente un archivo HTML. Y todo esto que ves debajo se encuentra dentro de las etiquetas<html></html>

html

 

 

Creando una rama en git para trabajar con estos archivos

Diagrama GitAhora me gustaría que antes de hacer un nuevo commit creemos una nueva rama a la que llamaremos “Desarrollo” donde esta nueva rama derivará de la principal “master” y entonces tendremos las versiones de nuestro proyecto divididas en según trabajemos sobre archivos de vistas, controladores o modelos de datos creando a partir de la rama “Desarrollo” las ramas “Vista“, “Controlador“, “Modelo” según vallamos modificando archivos, y siempre haremos un “Merge” a la rama “Desarrollo” hasta que tengamos una versión que funcione correctamente para fusionar en “master“. Y ¿por qué esta manera de trabajar el proyecto?. Simple, cuando tengamos algún error bastará con volver un commit hacía atrás en la correspondiente rama. Y sabremos a cada instante sobre que parte del proyecto estamos trabajando. Entonces no vas a liar nada y tendrás un excelente flujo de trabajo comprendiendo como funciona cada parte del modelo de tu proyecto!.

Así que a ello!

En nuestra terminal de Visual Studio vamos a crear una nueva rama de nuestro proyecto y luego hacer un commit en ella.

Creando la rama Desarrollo:

git checkout -b Desarrollo

Ahora vamos a hacer un commit en desarrollo:

git add .

git commit -m "(Modificando vistas) Añadida carpeta template y archivos index.html, contacto.html"




Si hacemos un:

git status

Veremos que estamos parados en la rama "Desarrollo".

Y ahora vamos a trabajar sobre el controlador. Así que ahora crea una rama llamada "Controlador":

git checkout -b Controlador

 

Renderizando un template HTML

Pero antes de salir de la rama Controlador de Git podemos aprovechar a modificar el retorno de las funciones de las rutas. Por ejemplo queremos la página inicial de nuestra app en vez de mostrar ese asqueroso y cutre “Hola mundo!” nos muestre mejor, la plantilla HTML (index.html) que hemos creado y guardado dentro de la carpeta “templates”. Así que vamos, sigamos modificando nuestro Controlador y archivo de configuración “run.py”. Para añadir esta funcionalidad debemos utilizar la función “render_template” de Jinja2 que recibirá como parámetro nuestro archivo HTML en vez de un simple return de texto feo.

Para ello importamos de flask a render_template, así:

#Importar
from flask import Flask, render_template


#Crear app medante instancia
app = Flask(__name__)


#Crear rutas con sus correspondientes funciones
@app.route('/', methods=['GET'])
def holamundo():
    return 'Hola Mundo!'

@app.route('/mis-proyectos', methods=['GET'])
def mostrarproyectos():
    return 'Aquí se mostrarán mis proyectos'

#Ejecutar nuestra app cuando ejecutemos este archivo run.py

if __name__ == '__main__':
    app.run(debug=True)

Fíjate que lo importamos en la linea 2 desde flask. Ahora vamos a modificar nuestro return para hacer uso de esta función que nos permite renderizar templates html. Para ello debemos añadir un:

return render_template(‘dirección de nuestro template’)

Y nuestro código quedaría así:

#Importar
from flask import Flask, render_template


#Crear app medante instancia
app = Flask(__name__)


#Crear rutas con sus correspondientes funciones
@app.route('/', methods=['GET'])
def holamundo():
    return render_template('templates/index.html')

@app.route('/mis-proyectos', methods=['GET'])
def mostrarproyectos():
    return 'Aquí se mostrarán mis proyectos'

#Ejecutar nuestra app cuando ejecutemos este archivo run.py

if __name__ == '__main__':
    app.run(debug=True)

Técnicamente iniciando nuestra aplicación Flask deberíamos ver un template HTML vacío. Has el intento..

python3 run.py

Pues no, nos encontramos con un error.. Pero a no perder la calma, bien podría editar el post, pero prefiero seguir para mostrarte como es un error de flask y como lo interpretamos:

error flask

Básicamente nos está diciendo que no se ha encontrado el template “index.html”. Y esto ocurre porque nosotros hemos especificado que el template se encuentra dentro de la carpeta “templates”, cuando en realidad FLASK está configurado automáticamente para buscar los archivos HTML dentro de esta carpeta.. así que nada la solución es sencilla, solo remueve ‘templates/’ y deja únicamente un ‘index.html‘ así:

#Importar
from flask import Flask, render_template


#Crear app medante instancia
app = Flask(__name__)


#Crear rutas con sus correspondientes funciones
@app.route('/', methods=['GET'])
def holamundo():
    return render_template('/index.html')

@app.route('/mis-proyectos', methods=['GET'])
def mostrarproyectos():
    return 'Aquí se mostrarán mis proyectos'

#Ejecutar nuestra app cuando ejecutemos este archivo run.py

if __name__ == '__main__':
    app.run(debug=True)

Y ahora sí, intenta nuevamente y obtendrás un HTML en blanco. Pero eso quiere decir que todo funciona correctamente.

Ahora vamos a crear un template para cada URL de nuestra página, en mi caso quisiera tener al menos 4 urls o rutas:

  1. El index o página de inicio
  2. Mis proyectos.
  3. Mi blog
  4. Contacto

Así que venga va!. Crear todas las plantillas HTML y añadir las urls a nuestras rutas, tal como lo venimos haciendo. Por supuesto modifica el hola mundo, ahora lo dejamos atrás, este es nuestro planeta. Por favor intenta comentar cada ruta al inicio (solo buenas prácticas). Y no olvides que las solicitudes en flask que estamos trabajando hasta ahora son GET, así que indicale a tu controlador el tipo de solicitud que debe admitir. Algo así:

#Importar
from flask import Flask, render_template


#Crear app medante instancia
app = Flask(__name__)


#Crear rutas con sus correspondientes funciones
#INICIO
@app.route('/', methods=['GET'])
def index():
    return render_template('/index.html')

#MIS PROYECTOS
@app.route('/mis-proyectos', methods=['GET'])
def mostrarproyectos():
    return render_template('mis-proyectos.html')

#MI BLOG
@app.route('/blog', methods=['GET'])
def blog():
    return render_template('/blog.html')

#CONTACTO
@app.route('/contacto', methods=['GET'])
def contacto():
    return render_template('/contacto.html')
#Ejecutar nuestra app cuando ejecutemos este archivo run.py

if __name__ == '__main__':
    app.run(debug=True)

Si todo funciona correctamente al visitar estas URL veremos solo páginas en blanco. Es momento de comenzar a trabajar en las VISTAS y modificar estos archivos HTML. Para ello debemos hacer “merge” de la rama Controlador con la rama Desarrollo y luego crear la rama VISTAS. Para trabajar las mismas en una nueva rama. A ello, en la terminal:

 

git status

git add .

git commit -m "Hemos añadido nuevas rutas y nuevos templates vacios para esas rutas"

Ahora nos paramos en la rama Desarrollo:

git checkout Desarrollo

Y Fusionamos a ella la rama Controlador:

git merge Controlador

 

Y listo. Podemos hacer un Push ahora para subir todos los cambios a nuestro repositorio remoto:

git push origin Desarrollo

 

Ahora asegúrate de estar parado sobre la rama Desarrollo:

git checkout

(Si estás sobre Desarrollo)

git checkout -b Vistas

Y ya tenemos nuestra rama Vistas.. Ahora a trabajar en los templates.

 

 

Crear un template BASE para flask e incluir Bootstrap

bootstrap

Bootstrap es un Framework Front-End, es decir que trabaja la parte de cara al usuario y nos permite desarrollar rápidamente páginas web siguiendo un determinado modelo por capas que resulta en un sitio web Resposive, es decir que se va a adaptar a cualquier pantalla, ya sea de un navegador de escritorio como de un móvil. Para instalar bootstrap hay diferentes formas pero yo prefiero la mas sencilla en este caso para no complicarnos la vida. Simplemente vamos a hacer uso de los archivos CSS y JS en línea añadiéndolo a un template PADRE o BASE!

Si quieres leer más sobre Bootstrap te invito a visitar los siguientes links:

 

Lo primero será crear un template BASE llamado “base.html“, este template contendrá todo lo que se repita en el sitio web, por ello se llama template base. Por ejemplo, podríamos verlo como un cascarón de fuera y donde dentro de un CONTENEDOR cargaremos las otras plantillas como el “index.html”, “mis-proyectos.html”, etc.

De esta forma nuestro templates incluirán al template “base.html” y no necesitaremos escribir en cada uno de nuestros templates el código que se repite. ¿Me comprendes Mendez?

Vamos a crear dentro de la carpeta “templates” otra carpeta llamada “base” y una carpeta llamada “nav”, esta ultima para una posterior barra de navegación. Verás que rápido nos montamos un sitio web chulisimo!.

Y dentro de las carpeta “base” creamos “base.html” al igual que lo hicimos con el index. Y dentro de la carpeta “nav” creamos “nav-bar.html” y este último si lo dejamos en blanco.

base html

Ahora antes que nada en “base.html” que será nuestra plantilla PADRE debemos añadir los archivos CSS y JS de Bootstrap. Para ello incluímos dentro de la etiqueta “head” el siguiente código:

<!--BOOTSTRAP CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

Y si lo deseamos antes del cierre del “body” podemos incluir los scripts de bootstrap:

<!-- jQuery first, then Popper.js, then Bootstrap JS -->
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
   <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
   <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

 

Con este código ya podemos hacer uso de bootstrap. Aquí puedes ver las distintas formas de instalación, nosotros en este caso simplemente nos serviremos los archivos de la CDN:

Así que nuestro template base.html quedaría así con bootstrap añadido:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!--BOOTSTRAP CSS --> 
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>
<body>


<!-- jQuery first, then Popper.js, then Bootstrap JS --> 
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script> 
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> 
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>   
</body>
</html>

 

Ahora vamos a añadirle un contenedor, y algunas columnas porque esto sigue siendo una página en blanco!

Este código del contenedor lo añadimos dentro del body de “base.html”, esto lo encuentras aquí en la documentación de Bootstrap.

<div class="container-fluid">   <!--Esto es un contenedor principal-->


</div>

 

Ahora dentro de ese div vamos a añadir otro container sencillo y una grilla de dos columnas, una ancha y otra angosta:

<div class="container">    <!-- Aquí estamos usando la clase "container" de Bootstrap --> 
      <div class="row">    <!-- Aquí estamos usando la clase "row" que significa "Fila", "o hilera"-->
      <div class="col-8">col-8</div>     <!-- Aquí nos esta creando una columna de tamaño 8--> 
      <div class="col-4">col-4</div>     <!-- Aquí nos esta creando una columna de tamaño 4--> 
    </div>                               <!--Cierra el row--> 
</div>                                   <!-- Cierra el container-->

Así nuestro template “base.html” quedaría (fíjate que he tratado de separar un poco el código para no perdernos):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!--BOOTSTRAP CSS --> 
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>



<body>
    <div class="container-fluid"> <!--Esto es un contenedor principal--> 
        <div class="container">    <!-- Aquí estamos usando la clase "container" de Bootstrap --> 
            <div class="row">    <!-- Aquí estamos usando la clase "row" que significa "Fila", "o hilera"-->
            <div class="col-8">col-8</div>     <!-- Aquí nos esta creando una columna de tamaño 8--> 
            <div class="col-4">col-4</div>     <!-- Aquí nos esta creando una columna de tamaño 4--> 
          </div>                               <!--Cierra el row--> 
      </div>                                   <!-- Cierra el container-->
    </div>




    
<!-- jQuery first, then Popper.js, then Bootstrap JS --> 
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script> 
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> 
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>   
</body>
</html>

 

Aprendiendo a usar bloques jinja2

Pero claro este template, nunca se va a mostrar.. Puesto que no esta en nuestras rutas.. Pero tampoco lo queremos allí, porque este es un template PADRE. Por lo que haremos un include en el resto de templates y este los tomará como templates HIJOS.

Pero antes fíjate que este template “base.html” que es un template padre ya tiene un título y nosotros queremos que tome el título de la página que esta mostrando dentro de los containers (queremos que muestre el título de la página hija). Por ello debemos de añadir un bloque de Jinja2 que cumple esta función dentro de la etiqueta “title”, fíjate en la línea 7 de nuestro template:

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title%} {%endblock%}</title>
    <!--BOOTSTRAP CSS --> 
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>



<body>
    <div class="container-fluid"> <!--Esto es un contenedor principal--> 
        <div class="container">    <!-- Aquí estamos usando la clase "container" de Bootstrap --> 
            <div class="row">    <!-- Aquí estamos usando la clase "row" que significa "Fila", "o hilera"-->
            <div class="col-8">col-8</div>     <!-- Aquí nos esta creando una columna de tamaño 8--> 
            <div class="col-4">col-4</div>     <!-- Aquí nos esta creando una columna de tamaño 4--> 
          </div>                               <!--Cierra el row--> 
      </div>                                   <!-- Cierra el container-->
    </div>





<!-- jQuery first, then Popper.js, then Bootstrap JS --> 
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script> 
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> 
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>   
</body>
</html>

 

Esta es la sintaxis que normalmente maneja JINJA2 dentro de corchetes o doble corchetes podemos incluir hasta bloques de código en Python3 aunque la idea es siempre tratar de procesar el código del lado del CONTROLADOR. En este caso JINJA2 reconoce que se trata de un bloque donde debe HEREDAR el Título de la plantilla HIJA.

También debemos indicarle donde se va a mostrar el contenido de la plantilla HIJA. Normalmente en el body claro, pero.. ¿En qué parte?. En este caso yo quiero que se muestre dentro de la columna más grande. Así que voy a añadirle un “block content“, que JINJA2 lo interpreta como “bloque de contenido” y allí es donde intentará mostrar el contenido de la página hija. Fíjate:

  1. Elimino col-8 que simplemente un texto ilustrativo y allí dentro de los divs que marcan la columna coloco la etiqueta de JINJA2 Block Content:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title%} {%endblock%}</title>
    <!--BOOTSTRAP CSS --> 
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>



<body>
    <div class="container-fluid"> <!--Esto es un contenedor principal--> 
        <div class="container">    <!-- Aquí estamos usando la clase "container" de Bootstrap --> 
            <div class="row">    <!-- Aquí estamos usando la clase "row" que significa "Fila", "o hilera"-->
            <div class="col-8">
                {% block content %}
                
                  {% endblock %}
            </div>     <!-- Aquí nos esta creando una columna de tamaño 8--> 
            <div class="col-4">col-4</div>     <!-- Aquí nos esta creando una columna de tamaño 4--> 
          </div>                               <!--Cierra el row--> 
      </div>                                   <!-- Cierra el container-->
    </div>





<!-- jQuery first, then Popper.js, then Bootstrap JS --> 
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script> 
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> 
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>   
</body>
</html>

 

WTF

Bien hasta aquí esta lista nuestra plantilla PADRE o BASE. Es momento de incluirla en las demás plantillas. Para ello vamos a las demás plantillas y vamos a borrar todo lo que hay dentro.. Ahora imagino tu cara!.

Pero si, ya no necesitamos nada más que lo que nuestra plantilla base va a mostrar dentro de “Block Content“. Así por ejemplo déjame explicarte antes que me mandes una carta documento.

Template base cargando index

 

 

Cuando carguemos por ejemplo la página “index” se cargará primero la plantilla “base.html” y dentro de ella, donde esta el código JINJA2 que acabamos de agregar, se cargará el contenido de “index.html“. Así que en index no necesitamos tener nada de etiquetas html, ni nada. Simplemente si quisiéramos podríamos tener hasta texto y ya..

Mira a la izquierda te lo explico con una diagrama cutre.

 

Antes de modificar más será mejor realizar un commit y un push en la rama vistas:

git add .
git commit -m "Añadidos template base.html incluido bootstrap y nav-bar.html"
git push origin Vistas

 

Ahora vamos a probar que todo esto que digo es cierto, vamos a la plantilla “index.html” borremos todo y hagamos un extend de la plantilla “base.html” y coloquemos el titulo y algo de texto, simple..:

{% extends "base/base.html" %}

{% block title %}Inicio{% endblock %}

{%block content %}

<!--Aquí el contenido a mostrar-->

{%endblock %}

Así quedaría nuestro “index.html”. Ahora notarás es puro código de Jinja2!. La primer linea “extends” significa que el archivo index se extiende a partir de base.html. O lo que sería lo mismo es una hija de “base.html”

Luego el siguiente bloque le dice cual es el título que debe mostrar, recuerdas que en la plantilla base habíamos colocado el mismo código en la parte del título.

Y finalmente también esta el “Block Content” que indica la parte única de index, es decir lo que se va a mostrar. Recuerdas que en “base.html” también colocamos este bloque dentro de la columna “col-8” pues allí se va a mostrar lo que pongas entre este bloque content!

Vamos a bootstrap y busquemos algo para mostrar y probar si todo funciona correctamente:

De allí obtengo el siguiente código y lo he editado creando una alerta entre el bloque content del index, quedando la plantilla index así:

{% extends "base/base.html" %}

{% block title %}Inicio{% endblock %}

{%block content %}
<br>
<div class="alert alert-success" role="alert">
    <h4 class="alert-heading">Aquí se muestra el contenido de las plantillas hijas!</h4>
    <p>Ahora si, este es un verdadero "HOLA MUNDO"</p>
    <hr>
    <p class="mb-0">Excelente!</p>
  </div>




{%endblock %}

Ahora ejecutemos:

python3 run.py

Y fíjate el resultado:

index bootstrap

 

Múltiples bloques en jinja2

Fíjate lo fácil que es organizar un sitio web con bootstrap y lo bonito que queda, con Bootstrap + Flask en cuestión de minutos puedes crear un sitio bonito y dinámico!

Pero hasta aquí el contenido de nuestras plantillas hijas solo se mostrará en la columna más grande de “base.html”. ¿Cómo hacemos para mostrar contenido de las plantillas hijas en la columna más pequeña?. Fácil añadiendo otro block content! pero para ello vamos a darle diferentes nombres, entonces nos organizamos mejor.

Así que vamos a tener dos bloques de contenido:

En vez de usar un solo {% block content %}{% endblock %} vamos a crear dos con estos nombres:

{%block columna8 %}
{%endblock %}
{% block columna4 %}
{% endblock %}

Y así para mostrar en una u otra columna simplemente debemos añadir el contenido dentro del bloque correspondiente. Pero este cambio debes aplicarlo de igual manera en “base.html” y en “index.html” pero en “base.html” los bloques estarán vacíos, y el en el “index.html” u otra plantilla los rellenarás con lo que tu quieras mostrar!

Fíjate como quedan ambos archivos:

base.html“:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title%} {%endblock%}</title>
    <!--BOOTSTRAP CSS --> 
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>
<body>
    <div class="container-fluid"> <!--Esto es un contenedor principal--> 
        <div class="container">    <!-- Aquí estamos usando la clase "container" de Bootstrap --> 
            <div class="row">    <!-- Aquí estamos usando la clase "row" que significa "Fila", "o hilera"-->
            <div class="col-8">
                {% block columna8 %}
                
                  {% endblock %}
            </div>     <!-- Aquí nos esta creando una columna de tamaño 8--> 
            <div class="col-4">
                {% block columna4 %}

                {% endblock %}



            </div>     <!-- Aquí nos esta creando una columna de tamaño 4--> 
          </div>                               <!--Cierra el row--> 
      </div>                                   <!-- Cierra el container-->
    </div>
<!-- jQuery first, then Popper.js, then Bootstrap JS --> 
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script> 
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> 
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>   
</body>
</html>

Y la plantilla “index.html

{% extends "base/base.html" %}

{% block title %}Inicio{% endblock %}

{%block columna8 %}

<br>
<div class="alert alert-success" role="alert">
    <h4 class="alert-heading">Aquí se muestra el contenido de las plantillas hijas!</h4>
    <p>Ahora si, este es un verdadero "HOLA MUNDO"</p>
    <hr>
    <p class="mb-0">Excelente!</p>
  </div>


{%endblock %}


  {% block columna4 %}
<p>Aquí se mostrará el contenido de la columna 4</p>

  {% endblock %}


Y como resultado veremos lo siguiente:

jinja2

Todo funcionando a la perfección!!. Ahora podemos gestionar lo que se muestra en cada columna!!

Ha llegado el momento de aprender a utilizar y gestionar solicitudes POST, y para ello vamos a usar ambas columnas, en una pediremos que se ingrese un nombre y la mostraremos en la otra!

 

Formularios básicos y solicitud POST

Vamos a crear un formulario básico, en este caso lo he sacado de Bootstrap Forms. Para facilitarnos las cosas, en este formulario vamos a solicitarle el nombre al visitante, nuestro “index.html” queda así:

{% extends "base/base.html" %}

{% block title %}Inicio{% endblock %}

{%block columna8 %}

<br>
<div class="alert alert-success" role="alert">
    <h4 class="alert-heading">Aquí se muestra el contenido de las plantillas hijas!</h4>
    <p>Ahora si, este es un verdadero "HOLA MUNDO"</p>
    <hr>
    <p class="mb-0">Excelente!</p>
  </div>


{%endblock %}


  {% block columna4 %}
<p>Formulario</p>
<form action="" method="post">
    <div class="form-group">
      <label for="name">Ingrese su nombre</label>
      <input type="text" class="form-control" name="Nombre">
    </div>
    <button type="submit" class="btn btn-primary">Enviar</button>
    </form>

  {% endblock %}

 

Vamos a explicar un poco el código. Cada vez que utilices un formulario en html este estará dentro de la etiqueta “form” y dentro de ella se detallan la acción a realizar de dicho formulario al dar en el botón “submit” así como también el método de envío de datos del formulario, donde en este caso hemos especificado el metodo POST, aunque también podríamos colocar GET y funcionaría igual, pero todos los datos enviados en el formulario se mostrarían en la URL de nuestra aplicación, y nadie quiere eso. Imagínate ver que tu contraseña aparece en una URL, sería catastrófico!.

Dentro del formulario nos encontramos con un Label, es decir, un bloque donde se mostrará algún texto y luego un Input de tipo Texto, donde un “input” es básicamente una etiqueta que refiere a la entrada de datos y los hay de diversos tipos, pero por ahora solo vamos a trabajar este, y más adelante conocerás los otros, o si eres curioso aquí puedes ver todas las etiquetas que admite un formulario HTML.

Nuestro formulario sencillito se ve así:

form

Pero si damos al botón de enviar nos aparece el siguiente error:

error Method not allowed

Y esto ocurre porque nuestro form aún no tiene definido una url dentro de “action” para ser procesado en caso de ser validado y tampoco estamos procesando el método POST en nuestro servidor. Así que es momento de modificar este form y añadirle una función:

Como estamos trabajando en el index, nuestro formulario será procesado en el “index.html“. ¿Y cuál es la url correspondiente al index?. Pues simplemente la barra invertida, fíjate en nuestro run.py

Así que modificamos nuestro formulario así:

<form action="/" method="post">
    <div class="form-group">
      <label for="name">Ingrese su nombre</label>
      <input type="text" class="form-control" name="Nombre">
    </div>
    <button type="submit" class="btn btn-primary">Enviar</button>
    </form>

Dentro de “action” ahora indica que será procesado en esa url. Ahora nuestra ruta de index aún no acepta solicitudes post, así que debemos encargarnos de ello para procesarla!. Vamos a nuestro run.py:

Y primeramente lo que hacemos es importar el modulo “request” que nos permitirá trabajar con las distintas solicitudes, y nos ayudará a manejar que hacer en caso de un GET o un POST.

from flask import Flask, render_template, request

Y también debemos aceptar las solicitudes de método POST en nuestro index, para ello modificamos donde anteriormente teníamos solo métodos GET, añadimos POST a la lista de argumentos en la url de index(), así:

#Importar
from flask import Flask, render_template, request
#Crear app medante instancia
app = Flask(__name__)
#Crear rutas con sus correspondientes funciones
#INICIO
@app.route('/', methods=['GET', 'POST'])
def index():
    return render_template('/index.html')
#MIS PROYECTOS
@app.route('/mis-proyectos', methods=['GET'])
def mostrarproyectos():
    return render_template('mis-proyectos.html')
#MI BLOG
@app.route('/blog', methods=['GET'])
def blog():
    return render_template('/blog.html')
#CONTACTO
@app.route('/contacto', methods=['GET'])
def contacto():
    return render_template('/contacto.html')
#Ejecutar nuestra app cuando ejecutemos este archivo run.py
if __name__ == '__main__':
    app.run(debug=True)

Ahora nuestra ruta index acepta solicitudes de método POST, pero:

¿Cómo sabemos cuando se tratará de una u otra?

No lo sabemos así que debemos especificar que sucederá cuando envíen una u otra. Y claro, cuando envíen una solicitud GET queremos que solo se cargue el sitio web. Y cuando envíen una solicitud POST queremos procesar los datos que esperamos, que sería el nombre del visitante para luego almacenarlo en una variable, recargar el sitio y mostrarlo en la otra columna con un mensaje de bienvenida. ¿Complejo he?. Na..

Ahora que tenemos importado request lo primero es utilizar un condicional IF dentro de la ruta index, entonces decimos Si es POST, haz esto. Sino entonces es GET, haz lo otro. De la siguiente manera y luego te explico el código línea por línea:

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        nombre = request.form['Nombre']
        return render_template('/index.html', nombre = nombre)
    else:
        return render_template('/index.html')
  1. Fíjate que desde la primer linea estamos aceptando ambos métodos de solicitud, tanto GET como POST.
  2. Segunda linea define la función que procesa la ruta “/” en este caso la habíamos llamado index()
  3. Y aquí es donde esta lo bueno, hacemos uso del módulo request y mediante un IF comprobamos si se trata de un método POST. Cuando aceptamos ambas solicitudes siempre es mejor comprobar primero si se trata de un método POST, y luego en caso que no (else) procesar el GET.
  4. Continuamos dentro del bloque IF que en caso de cumplirse que se trate de un método POST le dice al interprete almacene los datos del campo “Nombre” del formulario en la variable “nombre” haciendo uso también del modulo request pero esta vez solicitando datos del form. Y aquí fíjate bien porque luego es donde se dan los errores, este “Nombre” (con mayúsculas al inicio) es el nombre (name) del input del formulario del “index.html”, en caso de poner otro nombre no tomará el dato del campo input del formulario y se produciría un error.
  5. Ahora que ya estará almacenado los datos que el visitante ingreso en el formulario en la variable “nombre” recargamos la página haciendo el normal “return” del template, pero pasando la variable “nombre” como argumento!!
  6. Y luego metemos un “else” en caso de que no se trate de una solicitud POST, entonces se tratará de una GET. Por lo que en ese caso..
  7. Simplemente cargamos mediante el return el template de la misma forma que lo hacíamos antes.

Ahora fíjate en lo siguiente, que remarco muy importante para no confundirse:

burda explicación

Creo que no hace falta más explicación, el request del form debe indicar el nombre del campo input que se esta procesando. Así que así queda nuestro controlador run.py:

#Importar
from flask import Flask, render_template, request
#Crear app medante instancia
app = Flask(__name__)
#Crear rutas con sus correspondientes funciones
#INICIO
@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        nombre = request.form['Nombre']
        return render_template('/index.html', nombre = nombre)
    else:
        return render_template('/index.html')
#MIS PROYECTOS
@app.route('/mis-proyectos', methods=['GET'])
def mostrarproyectos():
    return render_template('mis-proyectos.html')
#MI BLOG
@app.route('/blog', methods=['GET'])
def blog():
    return render_template('/blog.html')
#CONTACTO
@app.route('/contacto', methods=['GET'])
def contacto():
    return render_template('/contacto.html')
#Ejecutar nuestra app cuando ejecutemos este archivo run.py
if __name__ == '__main__':
    app.run(debug=True)

 

Bien ya estamos listos. Ahora es momento de procesar esa variable nombre, en el “index.html“. Para ello voy a modificar la columna mayor y añadiré un mensaje de bienvenida y luego la variable para mostrar el nombre del visitante:

 

{% extends "base/base.html" %}

{% block title %}Inicio{% endblock %}

{%block columna8 %}

<br>
<div class="alert alert-success" role="alert">
    <h4 class="alert-heading">Bienvenido {{nombre}}</h4>
    <p>Ahora sabemos procesar solicitudes GET y POST!</p>
    <hr>
    <p class="mb-0">Excelente!</p>
  </div>


{%endblock %}


  {% block columna4 %}
<p>Formulario</p>
<form action="/" method="post">
    <div class="form-group">
      <label for="name">Ingrese su nombre</label>
      <input type="text" class="form-control" name="Nombre">
    </div>
    <button type="submit" class="btn btn-primary">Enviar</button>
    </form>

  {% endblock %}

Y este es el resultado, fíjate que chulería!

 


 

 

 

 

 

 

Y ya estamos, por hoy.. Me encanta!

Es momento de hacer un commit y fusionar la rama Vista a Desarrollo!

git add .
git status
git commit -m "Hemos aprendido a gestionar solicitudes GET y POST"
git checkout Desarrollo
git merge Vistas
git push origin Desarrollo

Recuerda que para mostrar el contenido de una variable en un archivo html como en este caso lo hemos hecho con “nombre” debemos pasarla como argumento en el controlador  y luego en el archivo html debemos hacer uso de jinja2 agregándola entre doble corchetes donde la queremos mostrar.

AdiosEn la próxima lección vamos a crear una barra de navegación y a dedicarnos de lleno a los templates para crear un portfolio donde añadiremos imágenes, links, etc. De esta forma iremos culminando este proyecto sencillo, para luego comenzar otro donde haremos uso de bases de datos y aprenderemos a organizar un proyecto para trabajar con proyectos de gran envergadura y muchos archivos! Espero te vallas contento con esta lección. Hasta la vista!!

 

Compartir es agradecer! :)

2 comentarios en “Solicitudes en FLASK (GET / POST) + Templates HTML”

Hey no te vayas sin dejarme un comentario!

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Aprende a programar de manera profesional!

¿Todavía sin obtener una retribución justa de tu aprendizaje?

Curso de Python Udemy

Convierteté en un verdadero Jedy de Python y comienza a desarrollar aplicaciones de forma profesional obteniendo un certificado de Udemy!. Pasate por la sección de Cursos Premium y realiza los mejores cursos con certificación válida a nivel internacional por apenas unos dolares!