miércoles, 1 de marzo de 2023

13.- Desarrollo práctico de una aplicación. Herencia Plantillas, Css y Bootstrap.

Formatear el sitio web con bootstrap.

Es un framework css que nos sirve para formatear un sitio web entero utilizando css. Es 'responsive' ya que nos sirve para que se vea bien en cualquier tipo de dispositivo y además es prácticamente compatible con todos los navegadores.

Volviendo a nuestro proyecto lo que perseguimos es dar a la página web un formato general para lo cual utilizaremos Bootstrap y también herencia de plantillas. Así conseguiremos que todas las páginas tengan unas zonas comunes y otras zonas específicas donde cargaremos el contenido correspondiente a cada página. En definitiva lo que queremos conseguir es mejorar la apariencia.

Link a bootstrap.

Para utilizar Bootstrap hay dos caminos:

1.- Linkar con los contenidos o librerías de Bootstrap de forma externa. 

2.- Descargarnos los contenidos para utilizarlo en local. En este caso utilizaremos django-bootstrap5 para integrar BootStrap en nuestro proyecto. Esta aplicación descarga los archivos que necesitaremos de Bootstrap, los coloca en los lugares apropiados dentro de nuestro proyecto y hace que las plantillas de estilo estén disponibles para uso. 

Para instalar Django-Bootstrap5 ejecutaremos la siguiente instrucción. Como comente al inicio del curso yo recomiendo hacerlo todo dentro de un entorno virtual. Se puede instalar a través de dos paquetes distintos. Elige uno u otro.

(entorno_virtual) $ pip install django-bootstrap5

* con este paquete tendrás que registrar la aplicación en settings 
  como 'django_bootstrap5'

o

(entorno_virtual) $ pip install django-bootstrap-v5

* con este paquete tendrás que registrar la aplicación en settings
  como 'bootstrap5'


A continuación tenemos que añadir el siguiente código para incluir Django-Bootstrap5 dentro de INSTALLED_APPS en el archivo settings.py del proyecto. Como he instalado el segundo paquete la registraré de la siguiente forma.


PracticaDjango/PracticaDjango/settings.py

INSTALLED_APPS = [
    # Mis aplicaciones.
    'Proyecto_web_app',
    # Aplicaciones de terceros.
    'bootstrap5',
    # Aplicaciones por defecto de Django
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',      
]

Asegúrate de que colocar esta aplicación 'bootstrap5' después de mis aplicaciones pero antes de las aplicaciones por defecto de Django.

A continuación vamos a ir al directorio de nuestra aplicación y crearemos una carpeta llamada static. Dentro de esta, crearemos otra con el nombre de la aplicación. Aquí irá todo el contenido estático, ya sean imágenes o código CSS. Su contenido no dependerá del contexto de la petición y será el mismo para todos los usuarios. Dentro de esta crearemos otras dos carpetas de momento. Una llamada css que como su nombre indica recogerá el código css de la aplicación y otra img donde guardaremos las imágenes que puedan utilizar las plantillas.

La estructura del directorio sería la siguiente:

/PracticaDjango -> 

    /Proyecto_web_app ->

       /static ->

                /Proyecto_web_app ->

                        /css

                        /img

Lo primero que tenemos que hacer es crear una plantilla que será el modelo para todas las demás plantillas que podamos crear. Se llamará base.html y de esta heredarán todas las demás. Como vamos a necesitar una barra de navegación crearé una muy sencilla que luego usare en la plantilla base. 

PracticaDjango/Proyecto_web_app/templates/Proyecto_web_app/nav.html

<nav>
    <ul>
        <li><a href="#">Home</a></li>
        <li><a href="#">Servicios</a></li>
        <li><a href="#">Blog</a></li>
        <li><a href="#">Tienda</a></li>
        <li><a href="#">Contacto</a></li>
    </ul>
</nav>

Y este sería el código de la plantilla base "base.html"

PracticaDjango/Proyecto_web_app/templates/Proyecto_web_app/base.html

<!DOCTYPE html>
<html lang="es">
<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>Página en Prueba</title>
</head>
<body>
    <header>
        <h1>UnikGAME TIENDA VIRTUAL</h1>
        <hr>
        <p>Barra de navegación insertada</p>
        {% include "Proyecto_web_app/nav.html" %}
    </header>
    <section>
        <p>Aquí irá la parte cambiante de la página</p>
    </section>
    <footer>
        <hr>
        <small>Politica de Privacidad . Aviso Legal . Cookies</small>
    </footer>
</body>
</html>


Herencia de Plantillas


La plantilla base.html va a ser nuestra plantilla madre. La vamos a utilizar para modificar las cinco plantillas hijas, que heredarán los elementos comunes de esta (header, barra de navegación y footer), y que se corresponderán con cada una de las páginas de nuestro sitio web. (Home, Servicios, Blog, Tienda y Contacto). Sin embargo, ten en cuenta que si una plantilla hija tiene algún elemento que también este definido en la plantilla padre, los elementos de esta última prevalecerán sobre las de la plantilla padre. 

Por ejemplo, en la plantilla padre has definido un determinado footer y en la hija otro distinto, el footer de la plantilla hija prevalece sobre la de la padre. No habrá herencia.

Empecemos modificando la plantilla base.html que ya tenemos para indicar las partes o bloques que las otras plantillas pueden escribir. Si tuviéramos hoja de estilos tendríamos que definirlas aquí. En este fichero incluiremos los bloques:

{% block title %} {% endblock %}
{% block content %} {% endblock %}

para definir el titulo y el contenido de las páginas hijas.

PracticaDjango/Proyecto_web_app/templates/Proyecto_web_app/base.html

<!DOCTYPE html>
<html lang="es">
<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>
</head>
<body>
    <header>
        <h1>UnikGAME TIENDA VIRTUAL</h1>
        <hr>
        <p>Barra de navegación insertada</p>
        {% include "Proyecto_web_app/nav.html" %}
    </header>
    <section>
        {% block content %}{% endblock %}
    </section>
    <footer>
        <hr>
        <small>Politica de Privacidad . Aviso Legal . Cookies</small>
    </footer>
</body>
</html>


Y AHORA VIENE LA GRACIA DEL ASUNTO....

Si te fijas la plantilla padre, base.html, tiene 24 líneas de código y sin contar las de la barra de navegación que están aparte en el archivo nav.html. Pues bien, si no usáramos herencia, tendríamos que copiar todo esto en cada una de las páginas que diseñemos, junto con las modificaciones necesarias para que mostrarán lo que queremos que aparezcan en cada una de ellas. Sin embargo usando la herencia:

PracticaDjango/Proyecto_web_app/templates/Proyecto_web_app/inicio.html

<!--Cargamos la plantilla base-->
{% extends "Proyecto_web_app/base.html" %}

<!-- Establecemos el titulo de la página -->
{% block title %}Home{% endblock %}

<!-- Definimos su contenido -->
{% block content %}
    <h2>Esta es la página de Inicio.</h2>
{% endblock %}
Esta primera plantilla hija la comenzamos diciendo que use la plantilla padre con la instrucción:

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

Para continuar reescribiendo los dos bloques, con lo que estamos diciendo al programa que busque estos bloques en la plantilla padre y que los sustituya por los que hemos puesto en esta plantilla.

El primero {% block title %} {% endblock %} modifica el título de la vista de inicio (HOME).

El segundo {% block content %} {% endblock %} mostrará el contenido propio de la página de inicio.

Este es el resultado.

Renderizado Página Home


Tenemos que modificar el resto de las cuatro plantillas exactamente de la misma forma. Una vez hecho lo anterior modificaremos el archivo nav.html que contiene el menú de navegación. Tiene que recoger la dirección de cada una de las páginas. Para obtener la URL de una vista en Django, podemos usar el siguiente código:

<a href="{% url 'nombre_de_la_vista' parámetros %}">Link a la vista</a>

donde el 'nombre_de_la_vista' vendrá definido como:

app_name:name  


Para ver de donde sale esto vamos a ir al archivo urls.py de nuestra aplicación Proyecto_web_app.


from django.urls import path
from . import views

app_name  = 'Proyecto_web_app'

urlpatterns = [
    path('', views.home, name='home'),
    path('servicios/', views.servicios, name='servicios'),
    path('tienda/', views.tienda, name='tienda'),
    path('blog/', views.blog, name='blog'),
    path('contacto/', views.contacto, name='contacto'),

]

Por ejemplo en mi ordenador al ejecutar el servidor, la dirección para la página de la tienda es:

http://127.0.0.1:8000/tienda/

Pues bien, al usar {% url 'Proyecto_web_app:tienda' %}, esta ya se construye automáticamente. Esto tiene la gran ventaja que si mas tarde queremos cambiar la url de alguna de las páginas no tendremos que tocar este archivo puesto que se construirán automáticamente.

Dicho lo cual el archivo nav.html quedaría de la siguiente forma.


PracticaDjango/Proyecto_web_app/templates/Proyecto_web_app/base.html

<nav>
    <ul>
        <li><a href="{% url 'Proyecto_web_app:home' %}">Home</a></li>
        <li><a href="{% url 'Proyecto_web_app:servicios' %}">Servicios</a></li>
        <li><a href="{% url 'Proyecto_web_app:blog' %}">Blog</a></li>
        <li><a href="{% url 'Proyecto_web_app:tienda' %}">Tienda</a></li>
        <li><a href="{% url 'Proyecto_web_app:contacto' %}">Contacto</a></li>
    </ul>
</nav>

También es posible pasar argumentos a la vista a través de la URL, agregando parámetros de la siguiente forma:

<a href="{% url 'nombre_de_la_vista' argumento1 argumento2 %}">Link a la vista con argumentos</a>


Dando formato a las plantillas con CSS y BootStrap.


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 styles.css, tenemos que guardarlo, como ya vimos, dentro de una carpeta llamada "static". En Django 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:

PracticaDjango / Proyecto_web_app/ static / Proyecto_web_app / css / styles.css

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

                    {% load static %}

                    <link rel="stylesheet" href="{% static 'Proyecto_web_app/css/styles.css' %}">

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. Para poder usarlo tenemos que iniciar el archivo base.html con:

                    {% load bootstrap5 %}

* o {% load django_bootstrap5 %} dependiendo del paquete utilizado.

y dentro de la etiqueta <head> usar el cargador:

                    {% bootstrap_css %} para usar las clases de bootstrap

                    {% bootstrap_javascript %} para usar java

                    {% bootstrap_messages %} para usar las alertas de Django.

De esta forma la cabecera del archivo base.html quedaría de la siguiente forma:

PracticaDjango/Proyecto_web_app/templates/Proyecto_web_app/base.html

{% load bootstrap5%}
{% load static %}
<!DOCTYPE html>
<html lang="es">
<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>
    
    <!-- Add Bootstrap CSS -->
    {% bootstrap_css %}
    {% bootstrap_javascript %}
    {% bootstrap_messages %}
<!-- Add additional CSS in static file --> <link rel="stylesheet" href="{% static 'Proyecto_web_app/css/styles.css' %}"> </head> ...

Rediseño del Header y de la barra de navegación.


Comenzamos con el header de la plantilla base.html.

PracticaDjango/Proyecto_web_app/templates/Proyecto_web_app/base.html

<header>
        <h1 class="container-fluid text-center text-white bg-dark py-5">
            UnikGAME
        </h1>
        {% include "Proyecto_web_app/nav.html" %}        
</header>
 A la etiqueta <h1> le aplicamos la clase "container-fluid" que es es un contenedor que ocupa todo el ancho de la ventana. También centramos el texto con text-center, le aplicamos un color blanco (text-white) y un fondo oscuro al contenedor con bg-dark. Para que el texto este centrado le aplicamos un padding tanto arriba como abajo de nivel 5. (py-5). Puedes encontrar información sobre estos elementos aquí.

Como incluimos la barra de navegación a través del archivo nav.htlm vamos a modificar el mismo.  Dentro de la documentación de Bootstrap si entramos en la sección de documentación y bajamos a Components encontramos ejemplos de muchos elementos. Dentro de estos, esta Navs&tabs donde tenemos un ejemplo sencillo de barra de navegación que vamos a aplicar.

PracticaDjango/Proyecto_web_app/templates/Proyecto_web_app/nav.html

<ul class="nav justify-content-center my-2">

  <li class="nav-item px-lg-4">
    <a class="nav-link text-uppercase text-expanded" href="{% url 'Proyecto_web_app:home' %}">
    Home
    </a>
  </li>

  <li class="nav-item px-lg-4">
    <a class="nav-link text-uppercase text-expanded" href="{% url 'Proyecto_web_app:servicios' %}">
    Servicios
    </a>
  </li>

  <li class="nav-item px-lg-4">
    <a class="nav-link text-uppercase text-expanded" href="{% url 'Proyecto_web_app:blog' %}">
    Blog
    </a>
  </li>

  <li class="nav-item px-lg-4">
    <a class="nav-link text-uppercase text-expanded" href="{% url 'Proyecto_web_app:tienda' %}">
    Tienda
    </a>

  </li>
  <li class="nav-item px-lg-4">
    <a class="nav-link text-uppercase text-expanded" href="{% url 'Proyecto_web_app:contacto' %}">
    Contacto
    </a>
  </li>
  
</ul>


Con estos pocos cambios conseguimos que la base de las plantillas tenga ahora este aspecto.

sección header modificada con bootstrap

Para acabar de mejorar el diseño añadiremos un fondo a la página. 

PracticaDjango/Proyecto_web_app/templates/Proyecto_web_app/base.html

...
    <!-- Parte cambiante de las plantillas -->
    <div class="fondo">
    <section>
        {% block content %}{% endblock %}
    </section>
    </div>
...

PracticaDjango/Proyecto_web_app/static/Proyecto_web_app/css/styles.css

.fondo {
    background-image: url(../img/bg_main.jpg);
    height: 58vh;
    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
}
Retocaremos un poco tambien el footer:
... 
<div class="fondo">
        <section>
            {% block content%}{% endblock %}
        </section>
    </div>

    <footer class="footer bg-dark text-center text-white">
        <hr>
        <small>
            <a href="#">Política de privacidad</a> ·
            <a href="#">Aviso legal</a> ·
            <a href="#">Cookies</a>
        </small>
        <p class="py-2"><small>(c) UnikGAME 2023</small></p>
    </footer>
</body>
</html>

Quedaría una apariencia parecida a esta, común para todas las páginas.


pagina base finalizada


Parar finalizar vamos a añadir código para resaltar la página activa, cambiando el color azul del enlace por el negro.

{% if request.path == '/' %}text-black{% endif %}">

request.path nos dará la url de la página en la que nos encontramos. De esta forma si la url definida coincide con la que nos encontramos, se aplicará la clase text-black. El archivo nav.html quedaría de la siguiente forma:

PracticaDjango/Proyecto_web_app/templates/Proyecto_web_app/nav.html

<ul class="nav justify-content-center my-2">

    <li class="nav-item px-lg-4">
        {% url 'Proyecto_web_app:home' as home_url %}
        <a class="nav-link text-uppercase fw-bold text-expanded {% if request.path == home_url %}
        text-black{% endif %}" href="{{ home_url }}">Inicio</a>
    </li>

    <li class="nav-item px-lg-4">
        {% url 'Proyecto_web_app:servicios' as servicios_url %}
        <a class="nav-link text-uppercase fw-bold text-expanded {% if request.path == servicios_url %}
        text-black{% endif %}" href="{{ servicios_url }}">Servicios</a>
    </li>

    <li class="nav-item px-lg-4">
        {% url 'Proyecto_web_app:blog' as blog_url %}
        <a class="nav-link text-uppercase fw-bold text-expanded {% if request.path == blog_url %}
        text-black{% endif %}" href="{{ blog_url }}">Blog</a>
    </li>

    <li class="nav-item px-lg-4">
        {% url 'Proyecto_web_app:tienda' as tienda_url %}
        <a class="nav-link text-uppercase fw-bold text-expanded {% if request.path == tienda_url %}
        text-black{% endif %}" href="{{ tienda_url }}">Tienda</a>
    </li>

    <li class="nav-item px-lg-4">
        {% url 'Proyecto_web_app:contacto' as contacto_url %}
        <a class="nav-link text-uppercase fw-bold text-expanded {% if request.path == contacto_url %}
        text-black{% endif %}" href="{{ contacto_url }}">Contacto</a>
    </li>
</ul>

1. `<ul class="nav justify-content-center my-2">`: Esto define una lista no ordenada (ul) con algunas clases de Bootstrap, como "nav" y "justify-content-center", para crear una barra de navegación centrada en la página.

2. Cada elemento de la lista (li) representa un enlace en la barra de navegación.

3. `{% url 'Proyecto_web_app:nombre_de_la_vista' as nombre_de_url %}`: Estas líneas utilizan la plantilla de Django para generar la URL de una vista de Django y asignarla a una variable llamada "nombre_de_url." Esto permite que el código sea más limpio y evita repetir la generación de URLs en cada enlace.

4. `<a>`: Cada enlace (`<a>`) contiene clases de Bootstrap y utiliza la variable previamente definida, como `{{ home_url }}`, para definir el atributo "href" con la URL correspondiente a la vista.

5. `{% if request.path == nombre_de_url %}text-black{% endif %}`: Esta es una condición que verifica si la URL actual (`request.path`) coincide con la URL generada para el enlace (la variable "nombre_de_url"). Si es cierto, se agrega la clase "text-black" al enlace, lo que generalmente se utiliza para resaltar el enlace activo en la barra de navegación.


Si por ejemplo pinchamos en la página 'blog' la página web quedaría de la siguiente manera:

resaltando el enlace



No hay comentarios:

Publicar un comentario