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.
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.
Django proporciona varias señales predefinidas, entre las más comunes se encuentran:
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.
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)
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,
)
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.')
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
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.')
Para más información sobre signals en Django, consulta la documentación oficial de Django.
Jorge García
Fullstack developer