Volver a la página principal
miércoles 16 octubre 2024
3

Cómo usar signals en Django

Las signals en Django son una poderosa herramienta que permite disparar ciertas acciones en respuesta a eventos específicos del ciclo de vida de las aplicaciones. Estas señales permiten que los componentes de una aplicación se comuniquen entre sí sin necesidad de estar estrechamente acoplados, facilitando el desarrollo de funcionalidades como el registro de actividades, la creación automática de perfiles de usuario, o el envío de correos electrónicos después de una acción.

¿Qué es una Signal en Django?

Una signal es un mecanismo que permite a ciertos eventos (como la creación o actualización de un objeto) emitir notificaciones, a las cuales otras partes de la aplicación pueden "escuchar" y reaccionar. Django incluye varias señales predefinidas y también permite crear señales personalizadas.

Señales comunes en Django

Django proporciona varias señales predefinidas, entre las más comunes se encuentran:

  • pre_save: Se dispara antes de que un modelo sea guardado.
  • post_save: Se dispara después de que un modelo haya sido guardado.
  • pre_delete: Se dispara antes de que un objeto sea eliminado.
  • post_delete: Se dispara después de que un objeto haya sido eliminado.
  • m2m_changed: Se dispara cuando una relación de "muchos a muchos" (ManyToMany) es modificada.

Cómo conectar y utilizar signals

Para utilizar una signal, primero debes "conectarla" a un receptor (una función que se ejecuta cuando la señal se dispara). El receptor es una función que se ejecutará automáticamente cuando ocurra el evento.

Ejemplo básico con post_save

Supongamos que queremos crear un perfil de usuario automáticamente cada vez que se registra un nuevo usuario. Usaremos la señal post_save que se dispara después de que un objeto ha sido guardado.

1. Crear un receptor (función) para la signal:

from django.db.models.signals import post_save
   from django.contrib.auth.models import User
   from django.dispatch import receiver
   from .models import Perfil

   @receiver(post_save, sender=User)
   def crear_perfil_usuario(sender, instance, created, **kwargs):
       if created:
           Perfil.objects.create(user=instance)

2. Conectar la señal a través de un decorador:

En este ejemplo, el decorador @receiver conecta la señal post_save con la función crear_perfil_usuario. Esto asegura que cada vez que se guarda un nuevo objeto de tipo User, se creará automáticamente un perfil asociado.

3. Uso manual de la señal:

También puedes conectar una signal manualmente:

post_save.connect(crear_perfil_usuario, sender=User)

Otros ejemplos de uso

Enviar un correo electrónico tras el registro de un usuario

Puedes utilizar la señal post_save para enviar un correo electrónico cuando un nuevo usuario se registre en tu aplicación.

from django.core.mail import send_mail
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver

@receiver(post_save, sender=User)
def enviar_email_bienvenida(sender, instance, created, **kwargs):
    if created:
        send_mail(
            'Bienvenido a nuestra plataforma',
            'Gracias por registrarte.',
            'noreply@miapp.com',
            [instance.email],
            fail_silently=False,
        )

Registrar la eliminación de objetos

Puedes usar la señal post_delete para registrar en un log cada vez que un objeto sea eliminado.

from django.db.models.signals import post_delete
from django.dispatch import receiver
from .models import Persona
import logging

logger = logging.getLogger(__name__)

@receiver(post_delete, sender=Persona)
def registrar_eliminacion_persona(sender, instance, **kwargs):
    logger.info(f'La persona {instance.nombre} ha sido eliminada.')

Conectar signals en archivos signals.py

Es una buena práctica organizar tus signals en un archivo separado, como signals.py, dentro de cada aplicación. Sin embargo, Django no carga este archivo automáticamente, por lo que debes importarlo manualmente.

1. Crear el archivo signals.py:

# mi_app/signals.py
   from django.db.models.signals import post_save
   from django.contrib.auth.models import User
   from django.dispatch import receiver
   from .models import Perfil

   @receiver(post_save, sender=User)
   def crear_perfil_usuario(sender, instance, created, **kwargs):
       if created:
           Perfil.objects.create(user=instance)

2. Cargar las señales en el archivo apps.py:

En el archivo apps.py de la aplicación, importa signals.py en el método ready() para asegurarte de que las señales se cargan cuando la aplicación está lista.

from django.apps import AppConfig

   class MiAppConfig(AppConfig):
       name = 'mi_app'

       def ready(self):
           import mi_app.signals

Algunos ejemplos

1. Crear un perfil de usuario tras el registro:

from django.db.models.signals import post_save
   from django.contrib.auth.models import User
   from django.dispatch import receiver
   from .models import Perfil

   @receiver(post_save, sender=User)
   def crear_perfil(sender, instance, created, **kwargs):
       if created:
           Perfil.objects.create(user=instance)

2. Registrar en el log cada vez que se elimina un objeto:

from django.db.models.signals import post_delete
   from django.dispatch import receiver
   from .models import Persona
   import logging

   logger = logging.getLogger(__name__)

   @receiver(post_delete, sender=Persona)
   def registrar_eliminacion(sender, instance, **kwargs):
       logger.info(f'{instance.nombre} ha sido eliminado.')

Referencia oficial

Para más información sobre signals en Django, consulta la documentación oficial de Django.

Compartir:
Creado por:
Author photo

Jorge García

Fullstack developer