Bloques jinja2 – Tutorial de FLASK

bloques jinja2En este post vamos a explayarnos en explicar los bloques jinja2 y a trabajar utilizando algunos de ellos para culminar de una buena vez nuestro pequeño proyecto de un portfolio de desarrollador!

Ya los he acostumbrado a una entrada al día, madre mía la que se me viene!. Pero bueno es por ustedes y por mí cabros.

Esto es lo que elegí, esto es lo que me llena el alma y me devuelve a la vida cada día de mi amarga existencia.

 

Ustedes no lo saben pero me estaréis ayudando a conseguir una changa (trabajo) que no es poco, mientras aprendéis a crear aplicaciones flask.

Ya con lo que hemos aprendido tenemos conocimientos más que suficientes para gestionar un proyecto pequeño. Pero luego las lecciones continuarán y próximamente vamos a crear un proyecto donde haremos uso de bases de datos y crearemos perfiles de usuario. Pero ahora, a lo que nos compete dijo petete!

¿Qué son los bloques jinja2?

Como saben Jinja2 es el motor de renderizado de templates para python que se encuentra incluido por defecto en FLASK. Jinja2 es quien nos facilita el desarrollo de las Vistas y nos permite separar el código de la parte lógica. Como recordaréis hablamos de ModeloVistaControlador, pues Jinja2 se encarga de las vistas.

Y Jinja2 tiene unas expresiones particulares que permiten añadir muchas características a un template, desde código Python directamente sobre el template, hasta procesamiento de variables e inclusión de archivos externos.

Así Jinja2 nos permitirá trabajar con bloques como si de html se tratara, normalmente encontraremos una etiqueta de apertura y una etiqueta que indica cierre. Por ejemplo:

{%block content%}

Contenido

{%endblock%}

En este caso podemos ver como se hace uso de corchetes y el símbolo de porcentaje. Pero no siempre es así, en el caso de las variables por ejemplo para mostrar el contenido de una variable se utiliza únicamente los corchetes dobles.

{{Nombres}}

A continuación iremos conociendo y trabajando mientras culminamos nuestro proyecto cada uno de esos bloques jinja2. Y al final te dejaré una lista y una explicación de cada uno para que te los lleves de tarea a la almohada.

Créeme, tu mente va a volar pensando todo lo que puedes hacer a partir de aquí con un poquito de tiempo libre y código Python3.

 

Añadiendo una barra de navegación en flask

Vamos a modificar mucho nuestro proyecto inicial, para ello vamos a crear una barra de navegación. Podríamos decir un tipo de menú con enlaces a las diferentes url’s de nuestro y proyecto y porque no a url’s externas. Sin más a darle chachara!
Ho pero antes, te creas una rama Vistas que derive de Desarrollo!!. Ya debes recordar como hacerlo a estas alturas!

Bueno venga ya:

git checkout Vistas
git add .
git status

 

Abrimos nuestro super proyecto en Visual Studio Code, vamos que nosotros podemos sacar el país adelante en un Pentium 4 con 40°C de calor y sin agua. Gracias que por aquí aún tenemos electricidad e internet, no nos han cortado las piernas aún!

Luego de abrir VS Code iniciar su entorno virtual:

source venv/bin/activate

En mi caso claro, cada ordenador es un mundo!

Como primer paso vamos a ir al sitio web de Bootstrap: NavBar’s en Bootstrap

Y elegiremos el código de algún formato de barra de navegación que nos guste, en mi caso elegí el siguiente, aquí les comparto el código:

<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="#">Navbar</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavDropdown">
    <ul class="navbar-nav">
      <li class="nav-item active">
        <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Features</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Pricing</a>
      </li>
      <li class="nav-item dropdown">
        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
          Dropdown link
        </a>
        <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
          <a class="dropdown-item" href="#">Action</a>
          <a class="dropdown-item" href="#">Another action</a>
          <a class="dropdown-item" href="#">Something else here</a>
        </div>
      </li>
    </ul>
  </div>
</nav>

Esta barra técnicamente se ve así:

Barra de navegación Bootstrap

Horrenda, horrible, un asco, una porquería. Podemos mejorarla claro, pero primero vamos a encargarnos de incluirla en nuestra aplicación web. Así que el código lo copiamos en el archivo que habíamos creado para este fin. ¿Recuerdas?

Ahora si, vamos a la carpeta de nuestro proyecto “nav/nav-bar.hml” y pegamos este código. Una vez pegado guardamos y debemos incluirlo en nuestra app. Lo mejor sería hacerlo en el template “base.html” si quieres que esté presente en toda la web!.. Pero no podemos usar un bloque “extend” de JINJA2. ¿Por qué?.

Bloques Jinja2 – Extends

El bloque “extends” se utiliza cuando queremos referirnos a extender código de una plantilla PADRE, como lo hicimos en index donde extendimos de base.html. Normalmente se trata de trabajar con herencia de plantillas. Pues aquí no es posible, porque es una barra de navegación y no una plantilla base. Lo ideal es usar el bloque “include“, de incluir!.

Bloques Jinja2 – Include

El bloque jinja2 que llamamos “include” nos permite incluir otros archivos HTML dentro de cualquier template HTML, sea dentro de nuestro template base “base.html” o en cualquier otro archivo HTML que deseemos. Básicamente permite incluir un HTML dentro de otro HTML. Algo realmente muy útil para poder trabajar y organizarnos en archivos HTML separados y no tener un solo archivo de miles de lineas de código. Así nuestro proyecto estará sub-dividido y cuando quieras modificar por ejemplo la barra de navegación, pues te vas al archivo de la barra. Y no tendrás que ni modificarlo en cada archivo HTML  (desarrollo común de una página en html) ni en un solo template base lleno de líneas de código!.

Sin más explicaciones, añadimos lo siguiente a nuestro template base.html inmediatamente después de la etiqueta “body“:

{% include "nav/nav-bar.html" %}

Y así sin más habremos incluido la barra de navegación en todas las páginas que extiendan del template base. Nuestro template base.html queda entonces así:

<!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>

    {% include "nav/nav-bar.html" %}

    <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>

meme virus

Me imagino que intentas leer e interpretar el código. ¿Verdad?.

No te me habrás mal acostumbrado y te me conviertas en un Zombi de corta y pega..

Es importante tratar de comprender lo que estamos haciendo, parte por parte e ir tomando alguna nota para poder repetir el proceso tu mismo cuando quieras crear un nuevo proyecto!

Lo siento por el meme, no me pude resistir jijiji!

 

Vamos a ver como quedo esa bendita barra, ya no te asusto más!

bloques en flask

Peeerooo siiiieees una monaaada!. Ahora vamos a modificar la horripilante barra, vamos a darle un estilo más chulo, en mi caso cambiaré los colores. Pero antes, ¿Sabías que hay una aplicación web para eso?.. Ajajammm!! Visita este sitio web y velo por ti mismo 😉

nopeAquí yo soy bastante haragán, no voy a perder tiempo en rehacer algo que ya existe (pero sí en entender como funciona). Podemos usar esta aplicación web para facilitarnos las cosas y más pronto que tarde aprenderás tu mismo HTML + CSS. Pero ahora nos ahorra tiempo, trabajo y dolores de cabeza que no vienen al caso, siempre, el tiempo vale oro, el nuestro y el de los demás y ni te digo el esfuerzo! Así que venga, hagamos uso de esta maravillosa App!

bar-nav-bar

Así quedó mi barra. Bueno sobre gustos, colores!

Ahora, ¿cómo hacemos para que la nuestra se vea así?. Pues debemos importar el CSS que esta App nos tiró por debajo. Para ello deberemos obligadamente crear un archivo CSS e incluirlo en el archivo de nuestra barra!

Para eso vamos a crear otra carpeta dentro de nuestro proyecto que llamaremos “static” y dentro de ella crearemos otra llamada “css“, dentro de esta un archivo llamado “nav-bar.css” donde solo incluiremos el CSS de nuestra Nav-Bar!. Allí pegamos el código que generó la app:

Nav-Bar CSS

Bueno ya tenemos el CSS a salvo en un archivo ahora lo vamos a incluir dentro de nuestro archivo html “nav-bar.html” correspondiente a la barra. Quedando este último así:

<link rel="stylesheet" href="{{ url_for('static', filename='css/nav-bar.css' ) }}">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNavDropdown">
      <ul class="navbar-nav">
        <li class="nav-item active">
          <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#">Features</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#">Pricing</a>
        </li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
            Dropdown link
          </a>
          <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
            <a class="dropdown-item" href="#">Action</a>
            <a class="dropdown-item" href="#">Another action</a>
            <a class="dropdown-item" href="#">Something else here</a>
          </div>
        </li>
      </ul>
    </div>
  </nav>

Aquí hay algo que no puedo dejar pasar:

Como habrás visto el código para insertar el CSS es el siguiente:

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

 

 

Bloques Jinja2 – url_for

Parecido a como normalmente se inserta el link a un CSS en html, pero con la diferencia que la URL del archivo nos encontramos con un bloque Jinja2, ¿lo reconoces?. Fíjate está entre corchetes!!. Este bloque “url_for” indica una url y se utiliza en Flask para redirigir a una url interna. Y siempre, siempre para insertar urls o links se usa “url_for“.

Por lo tanto “url_for” es un bloque que se utiliza para generar url’s dinámicas permitiendo añadir diversos parámetros, como en este caso se especifica “static” lo que refiere a que es un archivo estático por lo que se encontrará en la carpeta “static” que es la que acabamos de crear, por lo que no necesitas poner la url completa dentro de “url_for” como parámetro al haber especificado que se trata de un “static” si así no fuera deberías colocar la url completa como parámetro “filename”; “static/css/nav-bar.css”. Pero con “css/nav-bar.css” bastará. Ya veremos luego porque se utiliza dentro de toda etiqueta que incluya una url, por ejemplo en las imágenes.

Por cierto aquí te copio el CSS de mi barra. Pero sería bueno diseñes la tuya propia, no que me copies la mía. Jumm!

.navbar {
    background-color: #292929;
  }
  .navbar .navbar-brand {
    color: #d114dd;
  }
  .navbar .navbar-brand:hover,
  .navbar .navbar-brand:focus {
    color: #61dfdf;
  }
  .navbar .navbar-text {
    color: #d114dd;
  }
  .navbar .navbar-text a {
    color: #61dfdf;
  }
  .navbar .navbar-text a:hover,
  .navbar .navbar-text a:focus {
    color: #61dfdf; 
  }
  .navbar .navbar-nav .nav-link {
    color: #d114dd;
    border-radius: .25rem;
    margin: 0 0.25em;
  }
  .navbar .navbar-nav .nav-link:not(.disabled):hover,
  .navbar .navbar-nav .nav-link:not(.disabled):focus {
    color: #61dfdf;
  }
  .navbar .navbar-nav .dropdown-menu {
    background-color: #292929;
    border-color: #6f0a8e;
  }
  .navbar .navbar-nav .dropdown-menu .dropdown-item {
    color: #d114dd;
  }
  .navbar .navbar-nav .dropdown-menu .dropdown-item:hover,
  .navbar .navbar-nav .dropdown-menu .dropdown-item:focus,
  .navbar .navbar-nav .dropdown-menu .dropdown-item.active {
    color: #61dfdf;
    background-color: #6f0a8e;
  }
  .navbar .navbar-nav .dropdown-menu .dropdown-divider {
    border-top-color: #6f0a8e;
  }
  .navbar .navbar-nav .nav-item.active .nav-link,
  .navbar .navbar-nav .nav-item.active .nav-link:hover,
  .navbar .navbar-nav .nav-item.active .nav-link:focus,
  .navbar .navbar-nav .nav-item.show .nav-link,
  .navbar .navbar-nav .nav-item.show .nav-link:hover,
  .navbar .navbar-nav .nav-item.show .nav-link:focus {
    color: #61dfdf;
    background-color: #6f0a8e;
  }
  .navbar .navbar-toggler {
    border-color: #6f0a8e;
  }
  .navbar .navbar-toggler:hover,
  .navbar .navbar-toggler:focus {
    background-color: #6f0a8e;
  }
  .navbar .navbar-toggler .navbar-toggler-icon {
    color: #d114dd;
  }
  .navbar .navbar-collapse,
  .navbar .navbar-form {
    border-color: #d114dd;
  }
  .navbar .navbar-link {
    color: #d114dd;
  }
  .navbar .navbar-link:hover {
    color: #61dfdf;
  }
  
  @media (max-width: 575px) {
    .navbar-expand-sm .navbar-nav .show .dropdown-menu .dropdown-item {
      color: #d114dd;
    }
    .navbar-expand-sm .navbar-nav .show .dropdown-menu .dropdown-item:hover,
    .navbar-expand-sm .navbar-nav .show .dropdown-menu .dropdown-item:focus {
      color: #61dfdf;
    }
    .navbar-expand-sm .navbar-nav .show .dropdown-menu .dropdown-item.active {
      color: #61dfdf;
      background-color: #6f0a8e;
    }
  }
  
  @media (max-width: 767px) {
    .navbar-expand-md .navbar-nav .show .dropdown-menu .dropdown-item {
      color: #d114dd;
    }
    .navbar-expand-md .navbar-nav .show .dropdown-menu .dropdown-item:hover,
    .navbar-expand-md .navbar-nav .show .dropdown-menu .dropdown-item:focus {
      color: #61dfdf;
    }
    .navbar-expand-md .navbar-nav .show .dropdown-menu .dropdown-item.active {
      color: #61dfdf;
      background-color: #6f0a8e;
    }
  }
  
  @media (max-width: 991px) {
    .navbar-expand-lg .navbar-nav .show .dropdown-menu .dropdown-item {
      color: #d114dd;
    }
    .navbar-expand-lg .navbar-nav .show .dropdown-menu .dropdown-item:hover,
    .navbar-expand-lg .navbar-nav .show .dropdown-menu .dropdown-item:focus {
      color: #61dfdf;
    }
    .navbar-expand-lg .navbar-nav .show .dropdown-menu .dropdown-item.active {
      color: #61dfdf;
      background-color: #6f0a8e;
    }
  }
  
  @media (max-width: 1199px) {
    .navbar-expand-xl .navbar-nav .show .dropdown-menu .dropdown-item {
      color: #d114dd;
    }
    .navbar-expand-xl .navbar-nav .show .dropdown-menu .dropdown-item:hover,
    .navbar-expand-xl .navbar-nav .show .dropdown-menu .dropdown-item:focus {
      color: #61dfdf;
    }
    .navbar-expand-xl .navbar-nav .show .dropdown-menu .dropdown-item.active {
      color: #61dfdf;
      background-color: #6f0a8e;
    }
  }
  
  .navbar-expand .navbar-nav .show .dropdown-menu .dropdown-item {
    color: #d114dd;
  }
  .navbar-expand .navbar-nav .show .dropdown-menu .dropdown-item:hover,
  .navbar-expand .navbar-nav .show .dropdown-menu .dropdown-item:focus {
    color: #61dfdf;
  }
  .navbar-expand .navbar-nav .show .dropdown-menu .dropdown-item.active {
    color: #61dfdf;
    background-color: #6f0a8e;
  }

 

Bueno bueno basta! Vamos a ver como se ve nuestra barra:

 

fail nav- bar

 

Pero, ¿Qué caraj..?. Se aplicó el CSS, pero aún aparece de color de fondo gris!!. El problema entonces debe estar dentro del html, en la parte de las clases Bootstrap. ¿No te parece?. Veamos..

 

nav-bar-html

 

Y tal como lo pensaba, fíjate que en la segunda linea esta indicando la clase navbar-light y bg-light (“lo que corresponde a estilos de colores y background [bg]). Por ende esta tomando el estilo del CSS de Bootstrap y no del que acabamos de añadir.. Así que bastará borrar esas clases del html quedando así:

 

correccion nav-bar

 

Y ahora, ta tan ta tan..

 

nav-bar-exito

 

Todo un éxito de diseño!. Pero… No me gusta que esté así tan arriba.. Vamos nuevamente a modificar el CSS para alinearla de otra manera más chunga!.

En la parte del CSS que abarca la barra de navegación en general, pues pasando de este primer bloque ya se trata de los colores del texto o bordes. Agrego un margen de algunos pixeles para que parezca que simplemente está flotando. Mi CSS fue modificado así:

 

modificar CSS
Esa flecha hermanoo!

 

Ahora se ve así:

nav-bar-megaexito-de-diseño
¿Habéis visto barra más mona?

Finalmente le agregue transparencia añadiendo al css:

.navbar {
    background-color: transparent;
    background-color: rgba(0,0,0,0.5);
    margin-top: 15px;
    margin-right: 15px;
    margin-left: 15px;
  }
  .navbar .navbar-brand {
    color: #d114dd;
  }
  .navbar .navbar-brand:hover,
  .navbar .navbar-brand:focus {
    color: #61dfdf;
  }
  .navbar .navbar-text {
    color: #d114dd;
  }
  .navbar .navbar-text a {
    color: #61dfdf;
  }
  .navbar .navbar-text a:hover,
  .navbar .navbar-text a:focus {
    color: #61dfdf; 
  }
  .navbar .navbar-nav .nav-link {
    color: #d114dd;
    border-radius: .25rem;
    margin: 0 0.25em;
  }
  .navbar .navbar-nav .nav-link:not(.disabled):hover,
  .navbar .navbar-nav .nav-link:not(.disabled):focus {
    color: #61dfdf;
  }
  .navbar .navbar-nav .dropdown-menu {
    background-color: #292929;
    border-color: #6f0a8e;
  }
  .navbar .navbar-nav .dropdown-menu .dropdown-item {
    color: #d114dd;
  }
  .navbar .navbar-nav .dropdown-menu .dropdown-item:hover,
  .navbar .navbar-nav .dropdown-menu .dropdown-item:focus,
  .navbar .navbar-nav .dropdown-menu .dropdown-item.active {
    color: #61dfdf;
    background-color: #6f0a8e;
  }
  .navbar .navbar-nav .dropdown-menu .dropdown-divider {
    border-top-color: #6f0a8e;
  }
  .navbar .navbar-nav .nav-item.active .nav-link,
  .navbar .navbar-nav .nav-item.active .nav-link:hover,
  .navbar .navbar-nav .nav-item.active .nav-link:focus,
  .navbar .navbar-nav .nav-item.show .nav-link,
  .navbar .navbar-nav .nav-item.show .nav-link:hover,
  .navbar .navbar-nav .nav-item.show .nav-link:focus {
    color: #61dfdf;
    background-color: #6f0a8e;
  }
  .navbar .navbar-toggler {
    border-color: #6f0a8e;
  }
  .navbar .navbar-toggler:hover,
  .navbar .navbar-toggler:focus {
    background-color: #6f0a8e;
  }
  .navbar .navbar-toggler .navbar-toggler-icon {
    color: #d114dd;
  }
  .navbar .navbar-collapse,
  .navbar .navbar-form {
    border-color: #d114dd;
  }
  .navbar .navbar-link {
    color: #d114dd;
  }
  .navbar .navbar-link:hover {
    color: #61dfdf;
  }
  
  @media (max-width: 575px) {
    .navbar-expand-sm .navbar-nav .show .dropdown-menu .dropdown-item {
      color: #d114dd;
    }
    .navbar-expand-sm .navbar-nav .show .dropdown-menu .dropdown-item:hover,
    .navbar-expand-sm .navbar-nav .show .dropdown-menu .dropdown-item:focus {
      color: #61dfdf;
    }
    .navbar-expand-sm .navbar-nav .show .dropdown-menu .dropdown-item.active {
      color: #61dfdf;
      background-color: #6f0a8e;
    }
  }
  
  @media (max-width: 767px) {
    .navbar-expand-md .navbar-nav .show .dropdown-menu .dropdown-item {
      color: #d114dd;
    }
    .navbar-expand-md .navbar-nav .show .dropdown-menu .dropdown-item:hover,
    .navbar-expand-md .navbar-nav .show .dropdown-menu .dropdown-item:focus {
      color: #61dfdf;
    }
    .navbar-expand-md .navbar-nav .show .dropdown-menu .dropdown-item.active {
      color: #61dfdf;
      background-color: #6f0a8e;
    }
  }
  
  @media (max-width: 991px) {
    .navbar-expand-lg .navbar-nav .show .dropdown-menu .dropdown-item {
      color: #d114dd;
    }
    .navbar-expand-lg .navbar-nav .show .dropdown-menu .dropdown-item:hover,
    .navbar-expand-lg .navbar-nav .show .dropdown-menu .dropdown-item:focus {
      color: #61dfdf;
    }
    .navbar-expand-lg .navbar-nav .show .dropdown-menu .dropdown-item.active {
      color: #61dfdf;
      background-color: #6f0a8e;
    }
  }
  
  @media (max-width: 1199px) {
    .navbar-expand-xl .navbar-nav .show .dropdown-menu .dropdown-item {
      color: #d114dd;
    }
    .navbar-expand-xl .navbar-nav .show .dropdown-menu .dropdown-item:hover,
    .navbar-expand-xl .navbar-nav .show .dropdown-menu .dropdown-item:focus {
      color: #61dfdf;
    }
    .navbar-expand-xl .navbar-nav .show .dropdown-menu .dropdown-item.active {
      color: #61dfdf;
      background-color: #6f0a8e;
    }
  }
  
  .navbar-expand .navbar-nav .show .dropdown-menu .dropdown-item {
    color: #d114dd;
  }
  .navbar-expand .navbar-nav .show .dropdown-menu .dropdown-item:hover,
  .navbar-expand .navbar-nav .show .dropdown-menu .dropdown-item:focus {
    color: #61dfdf;
  }
  .navbar-expand .navbar-nav .show .dropdown-menu .dropdown-item.active {
    color: #61dfdf;
    background-color: #6f0a8e;
  }

 

Ahora haré un commit, porque ya considero que esta barra está lista en cuanto a estilo claro.

git commit -m "Añadida barra de navegación y archivos CSS correspondientes"

 

Vamos que venimos!. Ha llegado el momento de utilizar “url_for” que te había mencionado antes para añadir los links al resto de url’s de nuestro proyecto!. Así que vamos ahora al html de nuestra barra y vamos a modificarla de la siguiente manera:

USANDO URL_FOR EN EL HREF DE LOS LINKS:

 

{{ url_for('Nombre-de-la-función-de-la-vista')}}

Por ejemplo:

{{ url_for('index')}}

Quedando un link como:

<a href="{{ url_for('index')}}"></a>

 

Como ves en el vídeo hay varias cosas que destacar y una de ellas juro no haberme dado cuenta hasta recién.

  1. Url_for lleva como parámetro el nombre de la función de la ruta. No la URL en el caso de index sería “index” no “/“, he!
  2. Nos hemos olvidado de extender “base.html” en el resto de archivos HTML, por eso seguimos obteniendo páginas en blanco. ¿Por qué no me lo dijiste!!?. Ha claro, no puedes.. En fin, vamos a solucionar esto primero.
  3. Y por otro lado, si sabes algo de CSS te habrás percatado que la clase “item-nav active” muestra la página que esta activa. Pero como trabajamos con un include al cambiar de página seguirá mostrando a Inicio en el menú como página activa, ya verás el problemón pronto… Pero tranquilo chico, aquí hacemos contenido dinámico sin repetir código!. Ya verás que chulería de solución os traigo!!

Para solucionar el ítem numero 2 que te marque arriba en la lista, simplemente podemos copiar el código del “index.html” a los demás archivos modificando el título claro, y eliminando el contenido de dentro de las columnas:

Así he dejado el archivo “blog.html“:

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

{% block title %}Blog{% endblock %}

{%block columna8 %}

<br>
<div class="alert alert-success" role="alert">
    <h4 class="alert-heading">Bienvenido a mi blog</h4>
    <p>Aquí publicare entradas diariamente!</p>
    <hr>
    <p class="mb-0">Saludos!</p>
  </div>


{%endblock %}


  {% block columna4 %}
<p>Columna</p>


  {% endblock %}

Asi el archivo “mis-proyectos.html

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

{% block title %}Mis proyectos{% endblock %}

{%block columna8 %}

<br>
<div class="alert alert-success" role="alert">
    <h4 class="alert-heading">Echa un vistazo a mis proyectos en python!</h4>
    <p>Aquí verás un montón de proyectos con altura ;)</p>
    <hr>
    <p class="mb-0">Saludos!</p>
  </div>


{%endblock %}


  {% block columna4 %}
<p>Columna</p>


  {% endblock %}

 

Así el archivo “contacto.html“:

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

{% block title %}Contacto{% endblock %}

{%block columna8 %}

<br>
<div class="alert alert-success" role="alert">
    <h4 class="alert-heading">Estaré encantado de contactarte!</h4>
    <p>Aquí verás un formulario de contacto ;)</p>
    <hr>
    <p class="mb-0">Saludos!</p>
  </div>


{%endblock %}


  {% block columna4 %}
<p>Columna</p>


  {% endblock %}

Y listo!. Te copié todos los códigos, pero es simple editar un título y el contenido dentro de los bloques a su vez dentro de los divs de las columnas correspondientes. Vamos! Deberías hacerlo tú, pero como se que os gustan las cosas fáciles..

Ahora vamos a navegar un poco por nuestra web y comprenderás el PROBLEMA del que te hablaba antes con las clases de la barra de navegación “item-nav active“, fíjate:

 

¿Ahora entiendes el problema?. Al navegar sigue activa la página “Home”, que además me molesta que se llame así!. Ya en la barra lo cambio a “Inicio”. Y el item que esta activo está dictado por la clase de Bootstrap, y al cambiar de página ¿Cómo hacemos que cambie una clase del HTML si estamos trabajando con un include?. ¿Cuál crees sería una solución?

  • ¿Y si ponemos la barra en cada página HTML y allí modificamos la clase Bootstrap olvidando eso del “include”?
  • – Naaaa!!

Código Python 3 en jinja2

Apa!!. Esta solución es bestial!. ¿A que no te la esperabas!?. ¿Sabes qué?. Al diablo! Vamos a meter un IF en el HTML de la barra, más específicamente en la definición de la clase!! Y vamos a hacer uso de la función “request” que vimos anteriormente. En este caso particular del método “endpoint“. Mira:

Solución item-nav-active en flask

 

Flask-Jinja2 nos permite meter código Python 3 en el HTML. ¿Verdad que sí?. Pues podemos colocar un IF en donde ahora se encuentra la clase “nav-item” en cada ítem. Algo como:

Si la página-activa es index entonces usa esta clase “nav-item active” sino usa solo “nav-item”.

Pero.. ¿Cómo le hacemos saber cual es la página activa?

Usando “request.endpoint”!

¿Lo intentamos?. Vale, ¿como hacemos esto?. Modificando el HTML de la “nav-bar.html” teniendo en cuenta lo siguiente:

El método “endpoint” de la función “request” sirve para determinar la url en la que se encuentra el visitante. Es decir, que si te encuentras en “/blog”, este detectará la función de la ruta en la que te encuentras visitando!.

Por ende, el resto sale muy fácil así:

Modificamos el LI del menu así: 
<li class="nav-item {% if request.endpoint=='index' %}active{%endif %}">

Interpretamos el código más o menos así:

Asignamos la clase nav-item primero que nada. Luego continuamos con un IF que comprueba si nos encontramos en “index“, si es así, añade “active“. Y ya..

Porque si no nos encontramos en index la clase quedará simplemente “nav-item” porque el resto del IF no se cumple!. Un espectáculo digno de admirar!. La facilidad que nos otorga FLASK!

Así nuestro “nav-bar.html” quedaría:

<link rel="stylesheet" href="{{ url_for('static', filename='css/nav-bar.css' ) }}">
<nav class="navbar navbar-expand-lg navbar">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNavDropdown">
      <ul class="navbar-nav">
        <li class="nav-item {% if request.endpoint=='index' %}active{%endif %}">
          <a class="nav-link" href="{{ url_for('index')}}">Inicio <span class="sr-only">(current)</span></a>
        </li>
        <li class="nav-item {% if request.endpoint=='blog' %}active{%endif %}">
          <a class="nav-link" href="{{ url_for('blog')}}">Blog</a>
        </li>
        <li class="nav-item {% if request.endpoint=='mostrarproyectos' %}active{%endif %}">
          <a class="nav-link" href="{{ url_for('mostrarproyectos')}}">Mis proyectos</a>
        </li>
        <li class="nav-item {% if request.endpoint=='contacto' %}active{%endif %}">
            <a class="nav-link" href="{{ url_for('contacto')}}">Contacto</a>
          </li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
            Dropdown link
          </a>
          <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
            <a class="dropdown-item" href="#">Action</a>
            <a class="dropdown-item" href="#">Another action</a>
            <a class="dropdown-item" href="#">Something else here</a>
          </div>
        </li>
      </ul>
    </div>
  </nav>

Ahora mira que chulería:

Solución nav-item active

Y habrás notado lo fácil que resulta meter condicionales en el HTML!. Perooo, no hay que hacer abuso de ellos, solo para casos particulares en los que nos sentimos obligados a incrustarlos en la plantilla. Lo ideal es procesar el código en la parte del Controlador y no en las Vistas. Pero en algunos casos está permitido sobre todo cuando se trata de trabajar con algo referido a la parte visual como en este caso!

 

Bloques jinja2 – Condicionales IF

Es brujería
“Me temo que esto ya no es programación, es BRUJERÍA”.

Así como vimos anteriormente respetando esta sintaxis de bloques de JINJA2 podemos hacer uso de condicionales directamente desde el lado del template, aunque como dije antes no es recomendado. Por una cuestión de organización del proyecto, sobrecargas en el servidor y por atomicidad. Es decir, no queremos tener código regado por todos lados que luego no sepamos de donde proviene tal o cual resultado.

En el caso del ejemplo anterior lo hemos incrustado todo en una sola línea dentro de una definición de clase para determinado elemento HTML. Podemos hacer esto cuando nos sea útil!. Usa la imaginación y te vendrán miles de ideas a la cabeza.. Por ejemplo un botón en rojo o en verde según el usuario cumpla o no una condición, entre otras miles de brujerías con imágenes, estilos, etc.

 

Ahora también podemos en un template HTML colocar código Python y Javascript así:

{% if nombre|length > 0 %} 
<script type="text/javascript"> alert("Hola {{nombre}} eres un buen programador!"); </script> 
{% endif %}

Por ejemplo: intenta colocar este código en cualquier parte de tu index.html y coloca tu nombre en el formulario y verás como salta una alerta javascript.

Bueno bueno, ya deja de tontear con el código para alimentar tu ego de desarrollador!

Creo que si has aprendido Python 3 antes esto simplemente te resultará muy fácil de comprender..

Vamos rápido, pero a la vez despacio!
meme¿Qué dices?.. Vamos rápido ahora porque quiero mostrarte como realizar un proyecto utilizando estas tecnologías, pero luego en otra entrada me voy a dedicar a explicar todo. De-te-ni-da-men-te! Intentaré luego en un solo post volcar todo el contenido posible sobre FLASK y JINJA2 para que tengas allí una especie de Wiki disponible! Ahora nos enfocamos en este proyecto, que lo necesito, venga va!

 

Estilizando nuestro portfolio y añadiendo imágenes

A partir de aquí haré algunos cambios, sobre todo en el index.html y luego en la siguiente lección haremos un formulario de contacto!

Pero primero, commit!

git commit -m "Actualizada barra de navegación solucionado nav-item active"

base cssLo primero que me interesa es cambiar el color de fondo de nuestra web. Para ello vamos directo al CSS, pero deberemos crear otro archivo nuevo e incluirlo en el “base.html”. No es conveniente añadir CSS personalizado dentro del archivo que creamos anteriormente, porque este es solo para la barra de navegación y si luego queremos hacer algún cambio de estilos estará todo mezclado!. Así que en la carpeta “static/css” creamos un archivo “base.css“.

Luego en el css debemos especificar que los estilos que vamos a dar se aplicarán al “body“. Si hasta aquí no tienes una buena base de HTML+CSS créeme es cuestión de ponerse y en una horas en cualquier vídeo de Youtube te lo sacas. Nada de otro mundo!

Una vez creado nuestro CSS lo incluimos en el base al igual que hicimos con el CSS “nav-bar.css” en “nav-bar.hml“. ¿Recuerdas que debes utilizar “url_for“?. Entonces en base.html dentro del “head” añade:

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

Y ahora nuestro base.html queda así:

<!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">
    <!--MI CSS PERSONAL --> 
    <link rel="stylesheet" href="{{ url_for('static', filename='css/base.css' ) }}">
</head>
<body>

    {% include "nav/nav-bar.html" %}

    <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>

Ahora si podemos editar el archivo “static/css/base.css“. Yo añadí una imagen de fondo creando primero la carpeta “static/images” y cree un “div” para añadir una capa de degradado así (usando esta app de css).Ha y he optado también por crear la carpeta “static/js” y añadir un efecto utilizando Javascript.

No voy a explicar todo esto, porque en general ya no viene al caso. Digamos es la parte de desarrollo Frontend en la que no soy muy habilidoso, pero me las ingenio para llegar a un resultado “aceptable”, al menos por mi jajaja.

Finalmente, voy a copiar y pegar los códigos aquí para que tu puedas llegar al mismo resultado:

Código de nuestro sitio web Portfolio

Este es el código de todos los archivos que he modificado hasta ahora:

templates/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">
    <!--MI CSS PERSONAL --> 
    <link rel="stylesheet" href="{{ url_for('static', filename='css/base.css' ) }}">
</head>
<body>
    <div class = "capa1">
    {% include "nav/nav-bar.html" %}
    <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"> <!-- Aquí nos esta creando una columna de tamaño 8--> 
                
                {% block columna8 %}
            
                
                  {% endblock %}
            </div>   
            <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>
</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>   
<script src="{{ url_for('static', filename='js/tittle-efect.js' ) }}"></script> 
</body>
</html>

Fíjate que hemos añadido un div con la clase “capa1” para superponer un efecto de degradado sobre una imagen.

templates/index.html:

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

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

{%block columna8 %}
<h1>Python</h1>
<h1>Developer</h1>
<div class="word"></div>
{%endblock %}


  {% block columna4 %}


  {% endblock %}

Aquí simplemente añadí un titulo a modo de ejemplo y un div para el efecto Javascript, también de ejemplo!

static/css/base.css:

body{
  background-image: url('/static/images/wall.jpg');
  background-repeat: no-repeat;
  background-size:110%;
  
 
}
.capa1 {
    background: rgb(2,0,36);
    background: linear-gradient(90deg, rgba(2,0,36,0.8211659663865546) 0%, rgba(31,9,121,0.8911939775910365) 35%, rgba(188,0,255,0.5102415966386555) 100%);
    width: auto;
    min-height:800px;
}
.capa2 {
    background-color: transparent;
    background-color: rgba(106, 10, 185, 0.7);
 
}

h1{
    color: rgb(255, 255, 255) ;
    font-size:120px;
    text-shadow: 0px 5px 10px #320457,
    0px 10px 10px rgba(0,0,0,0.15),
    0px 15px 15px rgba(0,0,0,0.1),
    0px 20px 20px rgba(0,0,0,0.1);

}

.word {
  margin: auto;
  color: white;
  font: 700 normal 2.5em 'tahoma';
}

Aquí en el css base puedes ver como añadí una imagen de fondo y un degradado superpuesto en la clase “clase1”, entre otras cosas.

También modifique un poco el css de la barra.

static/css/nav-bar.css

.navbar {
    background-color: transparent;
    background-color: rgba(0,0,0,0.5);
  }
  .navbar .navbar-brand {
    color: #d114dd;
  }
  .navbar .navbar-brand:hover,
  .navbar .navbar-brand:focus {
    color: #61dfdf;
  }
  .navbar .navbar-text {
    color: #d114dd;
  }
  .navbar .navbar-text a {
    color: #61dfdf;
  }
  .navbar .navbar-text a:hover,
  .navbar .navbar-text a:focus {
    color: #61dfdf; 
  }
  .navbar .navbar-nav .nav-link {
    color: #d114dd;
    border-radius: .25rem;
    margin: 0 0.25em;
  }
  .navbar .navbar-nav .nav-link:not(.disabled):hover,
  .navbar .navbar-nav .nav-link:not(.disabled):focus {
    color: #61dfdf;
  }
  .navbar .navbar-nav .dropdown-menu {
    background-color: #292929;
    border-color: #6f0a8e;
  }
  .navbar .navbar-nav .dropdown-menu .dropdown-item {
    color: #d114dd;
  }
  .navbar .navbar-nav .dropdown-menu .dropdown-item:hover,
  .navbar .navbar-nav .dropdown-menu .dropdown-item:focus,
  .navbar .navbar-nav .dropdown-menu .dropdown-item.active {
    color: #61dfdf;
    background-color: #6f0a8e;
  }
  .navbar .navbar-nav .dropdown-menu .dropdown-divider {
    border-top-color: #6f0a8e;
  }
  .navbar .navbar-nav .nav-item.active .nav-link,
  .navbar .navbar-nav .nav-item.active .nav-link:hover,
  .navbar .navbar-nav .nav-item.active .nav-link:focus,
  .navbar .navbar-nav .nav-item.show .nav-link,
  .navbar .navbar-nav .nav-item.show .nav-link:hover,
  .navbar .navbar-nav .nav-item.show .nav-link:focus {
    color: #61dfdf;
    background-color: #6f0a8e;
  }
  .navbar .navbar-toggler {
    border-color: #6f0a8e;
  }
  .navbar .navbar-toggler:hover,
  .navbar .navbar-toggler:focus {
    background-color: #6f0a8e;
  }
  .navbar .navbar-toggler .navbar-toggler-icon {
    color: #d114dd;
  }
  .navbar .navbar-collapse,
  .navbar .navbar-form {
    border-color: #d114dd;
  }
  .navbar .navbar-link {
    color: #d114dd;
  }
  .navbar .navbar-link:hover {
    color: #61dfdf;
  }
  
  @media (max-width: 575px) {
    .navbar-expand-sm .navbar-nav .show .dropdown-menu .dropdown-item {
      color: #d114dd;
    }
    .navbar-expand-sm .navbar-nav .show .dropdown-menu .dropdown-item:hover,
    .navbar-expand-sm .navbar-nav .show .dropdown-menu .dropdown-item:focus {
      color: #61dfdf;
    }
    .navbar-expand-sm .navbar-nav .show .dropdown-menu .dropdown-item.active {
      color: #61dfdf;
      background-color: #6f0a8e;
    }
  }
  
  @media (max-width: 767px) {
    .navbar-expand-md .navbar-nav .show .dropdown-menu .dropdown-item {
      color: #d114dd;
    }
    .navbar-expand-md .navbar-nav .show .dropdown-menu .dropdown-item:hover,
    .navbar-expand-md .navbar-nav .show .dropdown-menu .dropdown-item:focus {
      color: #61dfdf;
    }
    .navbar-expand-md .navbar-nav .show .dropdown-menu .dropdown-item.active {
      color: #61dfdf;
      background-color: #6f0a8e;
    }
  }
  
  @media (max-width: 991px) {
    .navbar-expand-lg .navbar-nav .show .dropdown-menu .dropdown-item {
      color: #d114dd;
    }
    .navbar-expand-lg .navbar-nav .show .dropdown-menu .dropdown-item:hover,
    .navbar-expand-lg .navbar-nav .show .dropdown-menu .dropdown-item:focus {
      color: #61dfdf;
    }
    .navbar-expand-lg .navbar-nav .show .dropdown-menu .dropdown-item.active {
      color: #61dfdf;
      background-color: #6f0a8e;
    }
  }
  
  @media (max-width: 1199px) {
    .navbar-expand-xl .navbar-nav .show .dropdown-menu .dropdown-item {
      color: #d114dd;
    }
    .navbar-expand-xl .navbar-nav .show .dropdown-menu .dropdown-item:hover,
    .navbar-expand-xl .navbar-nav .show .dropdown-menu .dropdown-item:focus {
      color: #61dfdf;
    }
    .navbar-expand-xl .navbar-nav .show .dropdown-menu .dropdown-item.active {
      color: #61dfdf;
      background-color: #6f0a8e;
    }
  }
  
  .navbar-expand .navbar-nav .show .dropdown-menu .dropdown-item {
    color: #d114dd;
  }
  .navbar-expand .navbar-nav .show .dropdown-menu .dropdown-item:hover,
  .navbar-expand .navbar-nav .show .dropdown-menu .dropdown-item:focus {
    color: #61dfdf;
  }
  .navbar-expand .navbar-nav .show .dropdown-menu .dropdown-item.active {
    color: #61dfdf;
    background-color: #6f0a8e;
  }

Y por ultimo el script que agregue creando la carpeta y el archivo “static/js/tittle-efect.js” e incluí en base.html en una de las ultimas lineas usando “url_for” como es debido.

var words = ['Hi i like HTML', 'I also like css', 'Lorem ipsum dolor sit amet', ' consectetur adipiscing elit', 'sed do eiusmod tempor incididunt'],
    part,
    i = 0,
    offset = 0,
    len = words.length,
    forwards = true,
    skip_count = 0,
    skip_delay = 15,
    speed = 70;
var wordflick = function () {
  setInterval(function () {
    if (forwards) {
      if (offset >= words[i].length) {
        ++skip_count;
        if (skip_count == skip_delay) {
          forwards = false;
          skip_count = 0;
        }
      }
    }
    else {
      if (offset == 0) {
        forwards = true;
        i++;
        offset = 0;
        if (i >= len) {
          i = 0;
        }
      }
    }
    part = words[i].substr(0, offset);
    if (skip_count == 0) {
      if (forwards) {
        offset++;
      }
      else {
        offset--;
      }
    }
    $('.word').text(part);
  },speed);
};

$(document).ready(function () {
  wordflick();
});

 

Y este es el resultado:

portfolio

 

Consejos finales

Te recomiendo que aprendas por tu cuenta algo de HTML y CSS para poder diseñar buenos sitios webs. Pero de todas maneras usando Bootstrap siempre llegarás a un resultado aceptable. Se que por ahí cuesta un poco el tema de hacer buenos diseños y tal, pero te aconsejo que más allá de lo que has aprendido en este proyecto continúes con algo propio, por más crutre que te salga.

git status
git add .
git commit -m "Modificadas algunas caracteristicas de la parte visual o de diseño"
git checkout Desarrollo
git merge Vistas

 

adiósLa mejor forma de aprender es intentando, y practicando el intento, hasta el éxito una y otra vez!. Un abrazo mi querido lector!. Nos vemos en la siguiente lección, a no bajar los brazos ni quitar los dedos de ese teclado…

Nos vemos pronto, para hacer un formulario de contacto!.

 

Compartir es agradecer! :)

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!