jueves, 30 de julio de 2020

Flask 10. Plantillas con Bootstrap y Flask-bootstrap

Archivo:Bootstrap logo.svg


Plantillas con Bootstrap y Flask-bootstrap


   

En este capítulo nos vamos a detener un poco en el uso de hojas de estilo - CSS para mejorar la apariencia de las páginas html que estamos creando, que son sencillas pero funcionales. 

Aunque el Css lo podemos aplicar tanto desde la propia etiqueta de HTML, como dentro del archivo HTML, lo normal es que construyas la hoja de estilo en un archivo externo ya que de esta forma te vale para todas las páginas html que crees, básicamente entre otras muchas ventajas.

Si construimos nosotros mismos las hojas de estilo, por ejemplo en un archivo llamado style.css, tenemos que guardarlo, como ya vimos, dentro de una carpeta llamada "static". En flask esa carpeta "static" va a recoger todo lo relativo a contenido estático del proyecto (css, javascript, imagenes, pdf etc)

Mi archivo de ejemplo se encontrará en el siguiente directorio:

carpeta del proyecto / static / css / style.css

Y para cargarlo tendremos que utilizar la siguiente instrucción dentro de las etiquetas <head> de  la página html que queramos aplicarlo. 

<link rel="stylesheet" href="{{url_for('static', filename='css/style.css')}}" />

Por ejemplo, aprovechando los archivos que tenemos del capitulo anterior "Herencia de Plantillas", podemos cargar la hoja de estilos en la página padre, que hemos llamado base.html y de esta forma estarán disponibles por herencia para todas las páginas hijas.

Ahora bien, en vez de hacerlo tu mismo puedes utilizar el framework Bootstrap. Bootstrap te permite crear interfaces web con CSS y Javascript, visualmente más agradables, con elementos que ya están prediseñados y que además se adaptan al tamaño del dispositivo en el que se visualicen.

Esto lo podemos hacer de dos formas:

1) Como dice en la página de comienzo de Bootstrap (https://getbootstrap.com/). Hacemos click en "GET STARTED" y donde pone CSS copiamos y pegamos el enlace dentro de la etiqueta <head> de nuestra página e importante, antes de cualquier otra hoja de estilos que se cargue en la página:

Luego en el menú de la parte izquierda buscamos "Components" y ahí, buscamos el elemento que  queramos insertar en nuestro html (Botones, Barras de Navegación, Listas etc). Copiamos el código, lo pegamos en el archivo html que lo utilice y listo.

También puedes usarlo en local descargándolo de la página web e instalándolo en tu computadora. Normalmente en una fase de desarrollo es más cómodo utilizar primeramente el enlace y cuando hayas terminado el desarrollo y lo vayas a poner en funcionamiento, utilices el bootstrap descargado.

2) Instalando un complemento para Flask llamado Flask-Bootstrap, la ventaja que le veo es que te permite usar una plantilla base html que te facilitan, con lo que tu no tienes que crearla, y cuyos componentes heredarán el resto de las plantillas hijas. Luego le puedes añadir elementos que quieras o necesites usando bloques. 

Vamos a ver un ejemplo de css creado por nosotros, luego otro de Bootstrap puro y finalmente otro usando Flask-Bootstrap. En todos partimos de los archivos py, html y css del tema anterior "Herencia de Plantillas", concretamente de la plantilla padre, base.html. (que recuerda esté en el directorio "templates' junto con el resto de plantillas)


Ejemplo de CSS creado por nosotros en Flask.


Lo que pretendo es añadir un color rojo de Fondo a la etiqueta <h1> de la plantilla padre.

Empezamos cargando la hoja de estilos (style.css) en la plantilla base.html. Este fichero esta dentro de "static" y para separarlo del resto de posibles elementos estáticos esta a su vez dentro de un directorio llamado "css".

carpeta del proyecto / static / css / style.css

Lo hacemos agregando la siguiente instrucción en al final de la etiqueta <head> del archivo padre:

<link rel="stylesheet" href="{{url_for('static', filename='css/style.css')}}" />

Ahora creamos el código Css en

h1 {

background: red;

}

El resultado:


Ejemplo de CSS utilizando Bootstrap


Partimos del código del ejemplo anterior. 

Vamos a la página de Bootstrap y copiamos y pegamos el link con el código que nos dan para Css, justo antes del cargador de nuestro archivo propio de Css (el que hemos puesto en el ejemplo anterior):



Si solo con esto ejecutas el programa, verás que el estilo de la vista ya varía ligeramente con respecto al anterior:


Bien, en este ejemplo vamos a modificar la barra de navegación para ponerla en horizontal. La barra de navegación la tenemos incrustada en la plantilla base.html mediante un archivo externo llamado nav.html. 

Para usar una barra de navegación horizontal de Bootstrap, iremos a su pagína principal y en el menú de la izquierda buscamos el apartado "Components".  Si hacemos click en él se desplegará. Dentro de los componentes buscamos los menús de navegación que están en el apartado Navs. (https://getbootstrap.com/docs/4.5/components/navs/). He escogido el código de la más sencilla "Base nav"


Borramos todo el contenido de nav.html y copiamos y pegamos el código anterior previamente seleccionado. Quitamos el último enlace que no nos vale y modificamos los tres primeros, adaptándolos a los enlaces que tenemos en nuestro proyecto: Inicio, Página Uno y Sobre Nosotros.


Ahora ejecuta el proyecto y verás el siguiente resultado. (Puedes navegar entre las vistas para ver que funciona.)


Uso y ejemplo de Bootstrap mediante Flask-Bootstrap


Instalación de Flask-Bootstrap.


Tanto si estás utilizando un entorno virtual para el proyecto en cuyo caso lo tienes que tener activado, como si no lo estas haciendo, primeramente tenemos que instalar la extensión.


pip3 install Flask-Bootstrap


Configuración de nuestra aplicacion inicio.py




En el archivo inicio.py tenemos que modificar la cabecera del programa para que importe la extensión y para que la aplicación nos permita usar las diferentes plantillas. Para ello escribimos lo siguiente: (el código nuevo esta destacado en verde)



Está líneas generan una plantilla base de la que podemos extender las nuestras. Para que se entienda mejor, vamos a aplicarlo a nuestra plantilla base.html y la vamos a crear desde cero. El resto de archivos son los mismos que en el ejemplo anterior de Bootstrap puro. Por tanto, procedemos a borrar todo su contenido y empezamos usando la plantilla base.html que nos facilita flask_bootstrap

En nuestro fichero base.html escribimos:

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

Esta plantilla ya tiene todos los elementos que conforman una página html ( <head>, <body>, <style> etc). No está en ninguno de nuestros directorios simplemente la hemos importado. Como en Flask-bootstrap todo funciona con bloques, la siguiente línea de código definirá el título de cada página:

{% block title %} {% endblock %}


La plantilla base de bootstrap ofrece los siguientes bloques que podemos sobrescribir:

    • html: Contiene el contenido completo de la etiqueta <html>. 

    • html_attribs: Atributos para la etiqueta <html>. 

    • head: Contiene el contenido completo de la etiqueta <head>. 

    • body: Contiene el contenido completo de la etiqueta <body>. 

    • body_attribs: Atribulos para la etiqueta <body>. 

    • title: Contiene el contenido completo de la etiqueta <title>. 

    • styles: Contiene todos los estilos CSS de la etiqueta <link>. 

    • metas: Contiene los <meta> de la cabacera. 

    • navbar: Un bloque vacío encima del contenido. 

    • content: Bloque para poner nuestro contenido. 

    • scripts: Contiene todos los scripts en la etiqueta <script> al final del body. 


Puedes encontrar la lista completa de bloques aquí.


Ejemplos sacados de la página de flask-bootstrap

Añadiendo un fichero css creado por nosotros a la hoja de estilo:

{% block styles %}

{{super()}}

<link rel="stylesheet" href="{{url_for('.static', filename='mystyle.css')}}">

{% endblock %}


Añadiendo un fichero de javascript creado por nosotros al Javascript:

{% block scripts %}

{{super()}}

<script src="{{url_for('.static', filename='myscripts.js')}}"></script>

{% endblock %}


Añadiendo el idioma español en los atributos de <html>:

{% block html_attribs %} lang="es"{% endblock %}


Como habrás observado, en los ejemplos anteriores, cuando añadimos un nuevo archivo de hoja de estilos o de javascript se añade la función {{super()}}. Esta función lo que hace es añadir tu hojas de estilo o archivo de javascript a los que ya están definidos de forma estandar en bootstrap. 


No te olvides de ponerla o llamarla, ya que sino las hojas de estilo propias de bootstrap ¡desaparecerían al poner las tuyas!


Después de este paréntesis y siguiendo con nuestro ejemplo, vamos a añadir el resto de bloques que definirán nuestra plantilla padre y de las que heredaran las hijas:

 

Nota: en el archivo style.css he añadido:

.nav li {

    display: inline-block;

ya que si no el menú de navegación sale en vertical en vez de horizontal.

El resultado:


Con esto terminaríamos este apartado. 

Una matización final. Si estás utilizando {% block [....] %} para añadir diferentes elementos, por ejemplo headers o footers, pero te gustaría que estén siempre presentes en la página sin tener que invocarlos en cada una de las páginas hijas puedes hacer dos cosas:

1Poner en la plantilla base el contenido del header y el footer sin meterlo dentro de ninguna etiqueta block. Con esto siempre te saldrá, sin tener que invocarlo. El problema es que tampoco lo podrás quitar en ninguna plantilla que herede de esa. Si no lo vas a quitar nunca esta puede ser la mejor opción.
{# plantilla base: base.html #} 
<html>
  <head>
  ...
  </head>
 <body>
  <nav>
    <li>Inicio</li>
    <li>Página Uno</li>
    <li>Sobre nosotros</li>
  <nav>
  {% block content %}
  {% endblock %}
  <footer>
   ...
  </footer>
</body>
</html>

{# Plantilla hija #}
{% extends "base.html" %}
{% block content %}
<h1>Tutorial de Flask</h1>
<p>Lorem ipsum, lo otro y lo de más allá</p>
{% endblock %}
2.- Poner en la plantilla base el contenido de header y footer dentro de etiquetas block pero no invocar esos bloques desde la plantilla hija. De esta forma siempre saldrán porque las plantillas hijas siempre heredan de la padre. Pero si además, en una plantilla hija quieres que no aparezca nada en alguno de los bloques lo invocas en vacío. Y si quieres que aparezcan pero con otro contenido los invocas con ese contenido que entonces sustituirá al de la plantilla base.
{# Plantilla base: base.html #}
    <html>
      <head>
      ...
      </head>
      <body>
      {% block header %}
       <nav>
         <li>Inicio</li>
         <li>Página Uno</li>
         <li>Sobre nosotros</li>
       <nav>
      {% endblock %}
     
     {% block content %}
     {% endblock %}
     
     {% block footer %}
      <footer>
       ...
      </footer>
     {% endblock %}

    </body> 
</html> 

{# Plantilla hija #}
{% extends "base.html" %}
{% block content %}
<h1>Tutorial de Flask</h1>
<p>Lorem ipsum, lo otro y lo de más allá</p>
{% endblock %}

Código del Capítulo en Github.
Próximo Episodio. Formularios en Flask