Mostrando entradas con la etiqueta django. Mostrar todas las entradas
Mostrando entradas con la etiqueta django. Mostrar todas las entradas

miércoles, 20 de diciembre de 2023

20.2 Añadiendo autentificación con redes sociales en Django (Facebook, Twitter y Google)

La autenticación social es una característica ampliamente utilizada que permite a los usuarios autenticarse usando su cuenta existente de un proveedor de servicios mediante inicio de sesión único (SSO). El proceso de autenticación les permite a los usuarios iniciar sesión en el sitio utilizando su cuenta existente de servicios sociales como Google. En esta sección, agregaremos autenticación social al sitio utilizando Facebook, Twitter y Google.

Para implementar la autenticación social, utilizaremos el protocolo estándar de la industria OAuth 2.0 para autorización. OAuth significa Open Authorization. OAuth 2.0 es un estándar diseñado para permitir que un sitio web o aplicación acceda a recursos alojados por otras aplicaciones web en nombre de un usuario. Facebook, Twitter y Google utilizan el protocolo OAuth 2.0 para autenticación y autorización.

Python Social Auth es un módulo de Python que simplifica el proceso de agregar autenticación social a tu sitio web. Utilizando este módulo, puedes permitir que tus usuarios inicien sesión en tu sitio web utilizando sus cuentas de otros servicios. Puedes encontrar el código de este módulo en https://github.com/python-social-auth/social-app-django o en https://python-social-auth.readthedocs.io/en/latest/configuration/django.html

Este módulo viene con backends de autenticación para diferentes frameworks de Python, incluyendo Django. Para instalar el paquete de Django desde el repositorio Git del proyecto, abre la consola y ejecuta el siguiente comando dentro de tu entorno virtual:

venv$ pip install social-auth-app-django

Esto instalará Python Social Auth.

Luego, agrega 'social_django' al ajuste INSTALLED_APPS en el archivo settings.py del proyecto de la siguiente manera:

PracticaDjango/PracticaDjango/settings.py

INSTALLED_APPS = [
    # Nuestras aplicaciones
    'Proyecto_web_app.apps.ProyectoWebAppConfig',
    'Servicios.apps.ServiciosConfig',
    'Blog.apps.BlogConfig',
    'Contacto.apps.ContactoConfig',
    'Tienda.apps.TiendaConfig',
    'Carro.apps.CarroConfig',
    'Autentificacion.apps.AutentificacionConfig',
    # Aplicaciones de terceros
    'django_bootstrap5',
    'social_django',
    # Mapa del Sitio

Para que esto funcione necesitamos realizar la migración con:

python manage.py migrate


Python Social Auth incluye backends de autenticación para múltiples servicios. Puedes encontrar la lista con todos los backends disponibles en https://python-social-auth.readthedocs.io/en/latest/backends/index.html#supported-backends.

Vamos a añadir autenticación social a nuestro proyecto, permitiendo que nuestros usuarios se autentiquen con los backends de Facebook, Twitter y Google.

Primero, necesitamos añadir los patrones de URL de inicio de sesión social al proyecto.

Abre el archivo urls.py principal del proyecto, PracticaDjango y añade los patrones de URL de social_django de la siguiente manera. Las nuevas líneas están resaltadas en azul:


PracticaDjango/PracticaDjango/urls.py

#...

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('Proyecto_web_app.urls')),
    path('servicios/', include('Servicios.urls')),
    path('blog/', include('Blog.urls')),
    path('contacto/', include('Contacto.urls')),
    path('sitemap.xml', sitemap, {'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
    path('tienda/', include('Tienda.urls')),
    path('carro/', include('Carro.urls')),
    path('cuenta/', include('Autentificacion.urls')),
    path('social-auth/', include('social_django.urls', namespace='social')),
]
urlpatterns+=static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


Nuestra aplicación web actualmente es accesible a través de la IP de localhost 127.0.0.1 o usando el nombre de host localhost. Varios servicios sociales no permitirán redirigir a los usuarios a 127.0.0.1 o localhost después de una autenticación exitosa; esperan un nombre de dominio para la redirección de URL. Primero, necesitamos usar un nombre de dominio para que la autenticación social funcione. Afortunadamente, podemos simular servir nuestro sitio bajo un nombre de dominio en nuestra máquina local.

Localiza el archivo hosts de tu máquina. Si estás usando Linux o macOS, el archivo hosts se encuentra en /etc/hosts. Si estás usando Windows, el archivo hosts está en C:\Windows\System32\Drivers\etc\hosts.

Edita el archivo hosts de tu máquina y añade la siguiente línea:

127.0.0.1 misitio.com

en donde misitio.com es el nombre que quieras para tu nombre de dominio. En mi caso será "unikgame.com"

Esto indicará a tu computadora que el nombre de host misitio.com apunte a tu propia máquina.

Verifiquemos que la asociación del nombre de host funcionó. Ejecuta el servidor de desarrollo usando el siguiente comando desde la consola:

python manage.py runserver

Abre http://misitio.com:8000/account/login/ en tu navegador. Verás el siguiente error:

mensaje de error en la cabecera

Django controla los hosts que pueden servir la aplicación utilizando la configuración ALLOWED_HOSTS. Esta es una medida de seguridad para prevenir ataques de encabezado de host HTTP. Django solo permitirá que los hosts incluidos en esta lista sirvan la aplicación.

Puedes obtener más información sobre la configuración ALLOWED_HOSTS en https://docs.djangoproject.com/en/4.2/ref/settings/#allowed-hosts.

Edita el archivo settings.py del proyecto y modifica la configuración ALLOWED_HOSTS de la siguiente manera. El nuevo código está resaltado en negrita:

PracticaDjango/PracticaDjango/settings.py

#...
ALLOWED_HOSTS = ['misitio.com','localhost','127.0.0.1']


Además del host misitio.com, hemos incluido explícitamente localhost y 127.0.0.1. Esto permite el acceso al sitio a través de localhost y 127.0.0.1, que es el comportamiento predeterminado de Django cuando DEBUG es True y ALLOWED_HOSTS está vacío.

Abre nuevamente http://misitio.com:8000/cuenta/login/ en tu navegador. Ahora deberías ver la página de inicio de sesión del sitio en lugar de un error.


Ejecutando el servidor de desarrollo a través de HTTPS


Algunos de los métodos de autenticación social que vamos a usar requieren una conexión HTTPS. El protocolo de Seguridad de la Capa de Transporte (TLS) es el estándar para servir sitios web a través de una conexión segura. El predecesor de TLS es el Protocolo de Capa de Conexiones Seguras (SSL, por sus siglas en inglés).


Aunque SSL ahora está obsoleto, en múltiples bibliotecas y documentación en línea encontrarás referencias a los términos TLS y SSL. El servidor de desarrollo de Django no puede servir tu sitio a través de HTTPS, ya que ese no es su uso previsto. Para probar la funcionalidad de autenticación social sirviendo el sitio a través de HTTPS, vamos a utilizar la extensión RunServerPlus del paquete Django Extensions.


Django Extensions es una colección de extensiones personalizadas de terceros para Django. Ten en cuenta que nunca debes usar esto para servir tu sitio en un entorno real; este es solo un servidor de desarrollo.


Utiliza el siguiente comando para instalar Django Extensions:

$ pip install django-extensions

Necesitarás instalar Werkzeug, que contiene una capa de depuración requerida por la extensión RunServerPlus de Django Extensions. Utiliza el siguiente comando para instalar Werkzeug:

pip install werkzeug


Finalmente, utiliza el siguiente comando para instalar pyOpenSSL, que es necesario para usar la funcionalidad SSL/TLS de RunServerPlus:

pip install pyOpenSSL


Edita el archivo settings.py de tu proyecto y agrega Django Extensions al ajuste INSTALLED_APPS, de la siguiente manera:

PracticaDjango/PracticaDjango/settings.py

#...
INSTALLED_APPS = [
    # Nuestras aplicaciones
    'Proyecto_web_app.apps.ProyectoWebAppConfig',
    'Servicios.apps.ServiciosConfig',
    'Blog.apps.BlogConfig',
    'Contacto.apps.ContactoConfig',
    'Tienda.apps.TiendaConfig',
    'Carro.apps.CarroConfig',
    'Autentificacion.apps.AutentificacionConfig',
    # Aplicaciones de terceros
    'django_bootstrap5',
    'social_django',
    'django_extensions',
    # Mapa del Sitio


Ahora, usa el comando de gestión runserver_plus proporcionado por Django Extensions para ejecutar el servidor de desarrollo, de la siguiente manera:

python manage.py runserver_plus --cert-file cert.crt

Hemos proporcionado un nombre de archivo al comando runserver_plus para el certificado SSL/TLS. Django Extensions generará automáticamente una clave y un certificado.

Abre https://misitio.com:8000/cuenta/login/ en tu navegador. Ahora estás accediendo a tu sitio a través de HTTPS. Ten en cuenta que ahora estamos usando https:// en lugar de http://.

Tu navegador mostrará una advertencia de seguridad porque estás usando un certificado auto generado en lugar de un certificado confiable por una Autoridad de Certificación (CA).

Si estás utilizando Google Chrome, verás la siguiente pantalla:

mensaje de advertencia del navegador


En este caso, haz clic en "Avanzado" y luego haz clic en "Acceder a 127.0.0.1 (no seguro)".

Si estás utilizando otro navegador, accede a la información avanzada mostrada por tu navegador y acepta el certificado autofirmado para que tu navegador confíe en el certificado.

Verás que la URL comienza con https:// y, en algunos casos, un icono de candado que indica que la conexión es segura. Algunos navegadores pueden mostrar un icono de candado roto porque estás utilizando un certificado autofirmado en lugar de uno confiable. Eso no será un problema para nuestras pruebas.

¡Django Extensions incluye muchas otras herramientas y características interesantes! Puedes encontrar más información sobre este paquete en https://django-extensions.readthedocs.io/en/latest/.

¡Ahora puedes servir tu sitio a través de HTTPS durante el desarrollo para probar la autenticación social con Facebook, Twitter y Google!


Autentificación usando Facebook.


Para utilizar la autenticación de Facebook para iniciar sesión en tu sitio, agrega la siguiente línea, resaltada en negrita, al ajuste AUTHENTICATION_BACKENDS en el archivo settings.py de tu proyecto:

PracticaDjango/PracticaDjango/settings.py

#...
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'Autentificacion.autentificacion.EmailAuthBackend',
'social_core.backends.facebook.FacebookOAuth2',
]

Necesitaras crearte una cuenta de desarrollador de Facebook y luego crear una nueva aplicación de Facebook.

En tu navegador abre la siguiente dirección https://developers.facebook.com/apps/. Lo primero que tienes que hacer es logearte con la cuenta de Facebook y crear una cuenta de desarrollador. Te pedirán una serie de datos para verificar que eres tu. Una vez que hayas creado la cuenta de desarrollador verás la siguiente ventana:


pantalla inicial para crear aplicación

En la parte superior derecha haz clic en Crear aplicación.

Después verás una pantalla en la que se pueden seleccionar los casos más habituales de uso entre los desarrolladores. Selecciona el que pone "Authenticate and request data from users"


Authenticate and request data from users

Luego te preguntarán si estas desarrollando un juego o no:


¿Estás creando un juego o no?

A continuación verás el siguiente formulario para crear la aplicación:


Detalles de la aplicación

Donde pone "unikgame" introduce el nombre de tu aplicación, añade un email de contacto y haz clic en crear aplicación.

Luego ve a la parte izquierda de la pantalla. Haz clic en casos de uso y a la derecha haz clic en personalizar en el apartado de Autenticación y creación de cuenta. En la siguiente pantalla verás lo siguiente:

autenticacion y creacion de cuenta - personalizar

Haz clic en Ir a guía de inicio rápido.

El sistema te pedirá que elijas la plataforma para que vas a desarrollar la aplicación tal como se muestra en la siguiente imagen:

selección de plataforma para facebook login


Selecciona la plataforma web. Verás el siguiente formulario:

configuración de la plataforma web


Aquí tienes que introducir la URL que has configurado para tu sitio web de la forma https://misitio.com:8000/. En la imagen ves como he configurado yo mi página, tu tendrás que utilizar la que hayas configurado previamente. Después haz clic en continuar. Puedes saltarte el resto de opciones de guía de inicio rápido. Haz clic en la parte superior en el botón de volver dos veces hasta que vuelvas al panel de control de la aplicación.

Ahora, en la parte izquierda de la pantalla, haz clic en configuración de la aplicación y luego en información básica.

Panel de control de facebook


Verás un formulario con unos datos similares a los siguientes:


detalles de la aplicación

Copia el identificador de la aplicación (App ID)  y la Clave secreta de la aplicación (App Secret) y añádelas al archivo settings.py del proyecto de la siguiente forma:

PracticaDjango/PracticaDjango/settings.py

SOCIAL_AUTH_FACEBOOK_KEY = 'XXX' # Facebook App ID
SOCIAL_AUTH_FACEBOOK_SECRET = 'XXX' # Facebook App Secret

Opcionalmente, puedes definir SOCIAL_AUTH_FACEBOOK_SCOPE con los permisos adicionales que quieras requerir a los usuarios de Facebook, como por ejemplo el email:

PracticaDjango/PracticaDjango/settings.py

SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']

Ahora, vuelve la panel de control de aplicaciones de Facebook y haz clic en Configuración de la aplicación y acto seguido en información básica. Añade misitio.com en el campo Dominios de la aplicación (en mi caso sera unikgame.com)

También tienes que introducir una URL pública para el campo Privacy Policy URL y otra para el campo User Data Deletion Instruction URL. El siguiente es un ejemplo que usa la página de la Wikipedia como URL Privacy Policy. Por favor, date cuenta de que deberías usar tu propia URL válida:


Política de privacidad y condiciones de uso


Haz clic en guardar cambios. Luego, en la parte izquierda del menú hay que entrar en Casos de uso, luego a la derecha hacer clic en Personalizar y en la siguiente pantalla hacer clic en Ir a Configuración.

Comprueba que solo los siguientes ajustes estén activos:

• Client OAuth Login

• Web OAuth Login

• Enforce HTTPS

• Embedded Browser OAuth Login

• Used Strict Mode for Redirect URIs

y en el campo URI de redireccionamiento de OAuth válidos hay que introducir https://misitio.com:8000/social-auth/complete/facebook/ en donde misitio es el nombre de tu aplicación, en mi caso unikgame.com. Será algo como esto:

Cliente Oauth settings


Abre la plantilla registration/login.html de la aplicación Autentificacion y añade el siguiente código resaltado que añadirá el botón para registrarnos con la cuenta de Facebook en la parte inferior derecha de la plantilla:

PracticaDjango/Autentificacion/templates/registration/login.html

#...
<div class="login-form">
    <form action="{% url 'login' %}" method="post">
        {% csrf_token %}
        <div class="container w-25 bg-primary rounded-1">
            {% bootstrap_form form %}
            <input type="hidden" name="next" value="{{ next }}" />
            <p><input type="submit" value="Log-in"></p>
            <!-- {{ form.as_p }} -->
    </form>
    <p>
        <a href="{% url 'password_reset' %}" style="color:white">
            ¿Olvidaste tu contraseña?
        </a>
    </p>
</div>
<div class="social">
    <ul>
        <li class="facebook">
            <a href="{% url 'social:begin' 'facebook' %}">
                Haz Login con Facebook
            </a>
        </li>
    </ul>
</div>
{% endblock %}

Utiliza el comando de administración runserver_plus que nos proporciona Django Extensions para ejecutar el servidor de desarrollo de la siguiente manera:

python manage.py runserver_plus --cert-file cert.crt

Abre la siguiente dirección en tu navegador https://misitio.com:8000/cuenta/login/. Verás algo parecido a lo siguiente:


pagina para loguearse con Facebook

Haz clic en el botón Haz Login con Facebook. Serás redirigido a Facebook y verás un cuadro de dialogo pidiendo tu permiso para que tu aplicación acceda a tu perfil público de Facebook.

Permisos de la aplicación

Verás una advertencia que indica que necesitas enviar la aplicación para revisión de inicio de sesión. Haz clic en el botón Continuar como...

Serás conectado y redirigido a la página de inicio de tu sitio. Recuerda que has establecido esta URL en la configuración LOGIN_REDIRECT_URL. Como puedes ver, agregar autenticación social a tu sitio es bastante sencillo.


Autentificándose usando Twitter (ahora X)


Para loguearte usando twitter, añade la siguiente línea resaltada a los ajustes de autentificación del archivo settings.py de la aplicación.

PracticaDjango/PracticaDjango/settings.py

#...
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'Autentificacion.autentificacion.EmailAuthBackend',
'social_core.backends.facebook.FacebookOAuth2',
'social_core.backends.twitter.TwitterOAuth',
]

Necesitarás una cuenta de desarrollador de Twitter. Abre la dirección https://developer.twitter.com/ en tu navegador y haz clic en Sign Up. 

Después de crear una cuenta de desarrollador de Twitter, accede al panel de administración en la siguiente dirección https://developer.twitter.com/en/portal/dashboard. El panel de control debería tener un aspecto similar a este:

twitter developer poertal dashboard


Haz clic el botón "Create Project". Verás la siguiente pantalla:

Twitter create project screen – Use case

Introduce el nombre de tu proyecto y haz clic en Next.

En "Use Case" selecciona la opción que mejor se ajuste a porqué quieres usar el Api Twitter.  Esto no afectará a la configuración. 

descripción del uso del api de twitter


Después verás la siguiente pantalla:

Twitter create project screen – Project description

Introduce una breve descripción para tu proyecto y haz clic en Next. El proyecto ya está creado y verás la siguiente pantalla.

Twitter application configuration


Crearemos una nueva aplicación. Haz clic en Create New. Verás la siguiente pantalla para configurar la aplicación. 


En App name introduce el nombre de tu aplicación. Twitter no te permitirá introducir el nombre de un proyecto que ya exista por lo que debes ingresar un nombre que esté disponible. Haz clic en Next. Twitter te mostrará un error si el nombre que has introducido ya existe.

Después de escoger un nombre que este disponible, verás la siguiente pantalla.

Twitter application configuration – generated API keys

Copia de App Key y de Api Key Secret y pégalo en el archivo settings.py de tu proyecto.

PracticaDjango/PracticaDjango/settings.py

SOCIAL_AUTH_TWITTER_KEY = 'XXX' # Twitter API Key
SOCIAL_AUTH_TWITTER_SECRET = 'XXX' # Twitter API Secret

Después haz clic en App Settings. Después verás la siguiente pantalla en la que tendrás que volver a hacer clic en Set up.

configuración final de la aplicación

Al hacerlo tendrás que rellenar una serie de datos que están todos en la misma página. Son los siguientes:

conceder permisos a la aplicación

tipo de aplicación - web

En tipo de aplicación selecciona Web App.


En la pantalla de App Info introduce los siguientes detalles sobre tu aplicación:

Under General Authentication Settings, enter the following details of your application:

• Callback URI / Redirect URL: https://misitio.com:8000/social-auth/complete/twitter/

• Website URL: https://misitio.com:8000/

Los ajustes deberían parecerse a esto:


Twitter authentication URL configuration


Finalmente haz clic en Save. Ahora verás la siguiente pantalla que incluye el Client Id y el Client Secret.

twitter client id y client secret

No los necesitarás para la autentificación como cliente porque utilizaremos la clave Api Key y la clave Api Key Secret en su lugar. Sin embargo si te interesa puedes copiarlos y guardarlos en un lugar seguro. Haz clic en Done.

Verás otra pantalla que te recuerda que guardes tu Client Secret. 

Twitter Client Secret reminder

Haz clic en "Yes, I saved it".  

Abre la plantilla registration/login.html de la aplicación Autentificacion y añade el siguiente código resaltado que añadirá el botón para registrarnos con la cuenta de Twitter en la parte inferior derecha de la plantilla:


PracticaDjango/Autentificacion/templates/registration/login.html

#...

  <div class="social">
    <ul>
        <li class="facebook">
            <a href="{% url 'social:begin' 'facebook' %}">
                Login con Facebook
            </a>
        </li>
        <li class="twitter">
            <a href="{% url 'social:begin' 'twitter' %}">
                Login con Twitter
            </a>
        </li>
    </ul>
</div>

Utiliza el comando de administración runserver_plus que nos proporciona Django Extensions para ejecutar el servidor de desarrollo de la siguiente manera:

python manage.py runserver_plus --cert-file cert.crt

Abre la siguiente dirección en tu navegador https://misitio.com:8000/cuenta/login/. Busca en la parte inferior derecha y haz clic en "Login con Twitter". La aplicación te redireccionará a Twitter, donde te preguntarán si autorizas a tu aplicación, tal como se muestra en la siguiente imagen:

Twitter user authorization screen

Introduce tus datos e inicia sesión. Verás brevemente la siguiente página mientras eres redirigido a la página principal de la aplicación.

Twitter user authentication redirect page



Autentificación usando Google.


Google ofrece autenticación social utilizando OAuth2. Puedes leer sobre la implementación de OAuth2 de Google en https://developers.google.com/identity/protocols/OAuth2.

Para implementar la autenticación utilizando Google, agrega la siguiente línea resaltada en azul en la configuración AUTHENTICATION_BACKENDS en el archivo settings.py de tu proyecto:

PracticaDjango/Autentificacion/templates/registration/login.html

AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'Autentificacion.autentificacion.EmailAuthBackend',
'social_core.backends.facebook.FacebookOAuth2',
'social_core.backends.twitter.TwitterOAuth',
'social_core.backends.google.GoogleOAuth2',
]
Primero, necesitarás crear una clave API en tu Consola de Desarrollador de Google. Abre https://console.cloud.google.com/projectcreate en tu navegador. Verás la siguiente pantalla:

The Google project creation form

En Project name introduce el nombre de tu proyecto (En mi caso unikgame) y haz clic en el boton Create.

Cuando el nuevo proyecto esté listo, asegúrate de que el proyecto esté seleccionado en la barra de navegación superior de la siguiente manera:

The Google Developer Console top navigation bar


Después de que se cree el proyecto, a la izquierda en el panel que pone "Apis y Servicios" haz clic en credenciales.

Google APIs and services menu


Verás la siguiente pantalla:

Google API creation of API credentials

Haz clic en crear credenciales y luego en ID de cliente de OAuth.

Google te pedirá primero que aceptes la pantalla de consentimiento:

The alert to configure the OAuth consent screen

Configuraremos la página que se mostrará a los usuarios para que otorguen su consentimiento para acceder a tu sitio con su cuenta de Google. Haz clic en el botón CONFIGURAR PANTALLA DE CONSENTIMIENTO. Serás redirigido a la siguiente pantalla:

User type selection in the Google OAuth consent screen setup


Escoge "External" para el tipo de uso y haz clic en el botón "Create". Verás la siguiente pantalla:

Google OAuth consent screen setup


En App name introduce el nombre de tu aplicación (Unikgame en mi caso) y tu correo electrónico como correo de soporte. 

En "Authorised Domains" introduce misitio.com (en mi caso unikgame.com) de la siguiente forma:



Google OAuth authorized domains


Ingresa tu correo electrónico en la sección 'Información de contacto del desarrollador' y haz clic en GUARDAR Y CONTINUAR. En el paso 2, 'Ámbitos', no cambies nada y haz clic en GUARDAR Y CONTINUAR.

En el paso 3, 'Usuarios de prueba', añade tu usuario de Google a 'Usuarios de prueba' y haz clic en GUARDAR Y CONTINUAR de la siguiente manera:

Google OAuth test users


Verás un resumen de la configuración de tu pantalla de consentimiento. Haz clic en 'Volver al panel'.

En el menú de la barra lateral izquierda, haz clic en 'Credenciales' y luego en 'Crear credenciales' y después en 'ID de cliente de OAuth'.

Como siguiente paso, introduce la siguiente información:
Tipo de aplicación: Selecciona Aplicación web
Nombre: Ingresa el nombre de tu aplicación, en mi caso unikgame
Orígenes autorizados de JavaScript: Agrega https://misitio.com:8000
URIs de redireccionamiento autorizados: Agrega https://misitio.com:8000/social-auth/complete/googleoauth2/


The Google OAuth client ID creation form



The Google OAuth client ID creation form


Pulsa el botón CREAR. Obtendrás tus claves de 'ID de cliente' y 'Secreto de cliente':

Google OAuth Client ID and Client Secret


Añade ambas claves a tu archivo settings.py, de esta manera:

PracticaDjango/PracticaDjango/settings.py

#...
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = "XXX" # Google API Key
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = "XXX" # Google Client Secret
Edita la plantilla de registro/login.html y agrega el siguiente código resaltado en azul al
elemento <ul>:

PracticaDjango/Autentificacion/templates/registration/login.html

#...
<div class="social">
    <ul>
        <li class="facebook">
            <a href="{% url 'social:begin' 'facebook' %}">
                Login con Facebook
            </a>
        </li>
        <li class="twitter">
            <a href="{% url 'social:begin' 'twitter' %}">
                Login con Twitter
            </a>
        </li>
        <li class="google">
            <a href="{% url 'social:begin' 'google-oauth2' %}">
                Login con Google
            </a>
        </li>
    </ul>
</div>
Utiliza el comando de gestión runserver_plus proporcionado por Django Extensions para ejecutar el servidor de desarrollo de la siguiente manera:

python manage.py runserver_plus --cert-file cert.crt

Abre https://misitio.com:8000/account/login/ en tu navegador. En la parte inferior derecha haz clic en "Login con Google". Deberías poder loguearte y ser redireccionado a la página de inicio de la aplicación.



Creación de un perfil para usuarios que se registran con autenticación social. 



Cuando un usuario se autentica utilizando la autenticación social, se crea un nuevo objeto de Usuario si no existe un usuario asociado a ese perfil social. Python Social Auth utiliza un conjunto de funciones que se ejecutan en un orden específico durante el flujo de autenticación. Estas funciones se encargan de obtener los detalles del usuario, crear un perfil social en la base de datos y asociarlo a un usuario existente o crear uno nuevo.

Actualmente, no se crea un objeto de Perfil (Profile)  cuando se crean nuevos usuarios a través de la autenticación social. Aunque esto lo tenemos solventado en cierta forma ya que cuando editamos el usuario en esa vista introdujimos lo siguiente:


PracticaDjango/Autentificacion/views.py

#...
@login_required
def edit(request):
    try:
        profile = request.user.profile
    except Profile.DoesNotExist:
        profile = None
        
    if request.method == "POST":
        user_form = UserEditForm(instance=request.user, data=request.POST)
        if profile:
            profile_form = ProfileEditForm(
                instance=profile, data=request.POST, files=request.FILES
            )
        else:
Si el perfil existe se asigna a la variable "profile" y si no se crea una con el valor de None lo que evita que nos de un error al usar la vista.

Sin embargo para que esto todo mejor, vamos a agregar un nuevo paso al pipeline para crear automáticamente un objeto de Perfil en la base de datos cuando se crea un nuevo usuario.

Agrega la siguiente configuración SOCIAL_AUTH_PIPELINE al archivo settings.py de tu proyecto:

PracticaDjango/PracticaDjango/settings.py

#...
SOCIAL_AUTH_PIPELINE = [
'social_core.pipeline.social_auth.social_details',
'social_core.pipeline.social_auth.social_uid',
'social_core.pipeline.social_auth.auth_allowed',
'social_core.pipeline.social_auth.social_user',
'social_core.pipeline.user.get_username',
'social_core.pipeline.user.create_user',
'social_core.pipeline.social_auth.associate_user',
'social_core.pipeline.social_auth.load_extra_data',
'social_core.pipeline.user.user_details',
]
Este es el flujo de autenticación predeterminado utilizado por Python Social Auth. Consiste en varias funciones que realizan diferentes tareas al autenticar a un usuario. Puedes encontrar más detalles sobre el flujo de autenticación predeterminado en https://python-social-auth.readthedocs.io/en/latest/pipeline.html.

Construyamos una función que cree un objeto de Perfil en la base de datos cada vez que se crea un usuario nuevo. Luego agregaremos esta función al flujo de autenticación social.

Edita el archivo Autentificacion/autentificacion.py y agrega el siguiente código:

PracticaDjango/Autentificacion/autentificacion.py

#...
def create_profile(backend, user, *args, **kwargs):
    """
    Create user profile for social authentication
    """
    Profile.objects.get_or_create(user=user)
La función create_profile toma dos argumentos requeridos:

backend: El backend de autenticación social utilizado para la autenticación del usuario. Recuerda que has agregado los backends de autenticación social al ajuste AUTHENTICATION_BACKENDS en tu proyecto.

user: La instancia de Usuario del usuario nuevo o existente autenticado.
Puedes revisar los diferentes argumentos que se pasan a las funciones del flujo en https://pythonsocial-
auth.readthedocs.io/en/latest/pipeline.html#extending-the-pipeline.

En la función create_profile, verificamos que haya un objeto de usuario presente y utilizamos el método get_or_create() para buscar un objeto de Perfil para el usuario dado, creándolo si es necesario.

Ahora, necesitamos agregar la nueva función al flujo de autenticación. Agrega la siguiente línea resaltada en negrita al ajuste SOCIAL_AUTH_PIPELINE en tu archivo settings.py:

PracticaDjango/PracticaDjango/settings.py

#...
SOCIAL_AUTH_PIPELINE = [
'social_core.pipeline.social_auth.social_details',
'social_core.pipeline.social_auth.social_uid',
'social_core.pipeline.social_auth.auth_allowed',
'social_core.pipeline.social_auth.social_user',
'social_core.pipeline.user.get_username',
'social_core.pipeline.user.create_user',
'Autentificacion.autentificacion.create_profile',
'social_core.pipeline.social_auth.associate_user',
'social_core.pipeline.social_auth.load_extra_data',
'social_core.pipeline.user.user_details',
]
Hemos añadido la función create_profile después de social_core.pipeline.create_user. En este punto, una instancia de Usuario está disponible. El usuario puede ser un usuario existente o uno nuevo creado en este paso del flujo. La función create_profile utiliza la instancia de Usuario para buscar el objeto de Perfil relacionado y crear uno nuevo si es necesario.

Accede a la lista de usuarios en el sitio de administración en https://misitio.com:8000/admin/auth/user/. Elimina cualquier usuario creado mediante autenticación social.

Luego, abre https://misitio.com:8000/account/login/ e inicia sesión mediante autenticación social para el usuario que eliminaste. Se creará un nuevo usuario y ahora también se creará un objeto de Perfil. Accede a https://mysite.com:8000/admin/account/profile/ para verificar que se haya creado un perfil para el nuevo usuario.

Puedes encontrar el código de es Post en el siguiente enlace de GITHUB.

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