Signals

  • Understand Django Signals and implement event-driven functionality in applications.
  • What are Django Signals?

    Django Signals allow different parts of a Django project to communicate with each other.

    In simple words:

    “When something happens, automatically do something else.”

    Example:

    • User created → Create profile

    • Model saved → Send email

    • Data deleted → Log activity

    Real-Life Analogy

    Action

    Signal Reaction

    Student registered

    Welcome message

    Order placed

    Generate invoice

    Account deleted

    Remove related data

    Why Use Signals?

    • Automatic execution

    • Loose coupling (no direct dependency)

    • Cleaner code

    • Centralized business logic

    Where Signals are Used?

    • Model lifecycle events

    • Authentication events

    • Custom project events

    Types of Django Signals

    Built-in Django Signals

    Signal

    Trigger

    pre_save

    Before saving model

    post_save

    After saving model

    pre_delete

    Before delete

    post_delete

    After delete

    user_logged_in

    User login

    user_logged_out

    User logout


    Signal Flow

    Event Happens

         ↓

    Signal Emitted

         ↓

    Receiver Function

         ↓

    Action Performed

    Basic Signal Structure

Basic Signal Syntax

from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=ModelName)
def function_name(sender, instance, created, **kwargs):
    pass
  • Description

    • post_save → Signal

    • sender → Model triggering signal

    • instance → Saved object

    • created → True if new record

    Use-Case 1: Create Profile Automatically When User is Created

Profile Model

models.py

from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    phone = models.CharField(max_length=15)

User Post Save Signal

signals.py

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

@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
  • Description

    • Triggered after user creation

    • Automatically creates profile

Register Signals in apps.py

apps.py

from django.apps import AppConfig
class AccountsConfig(AppConfig):
    name = 'accounts'

    def ready(self):
        import accounts.signals
  • Use-Case 2: Send Email After Data Saved

Email Notification Signal

signals.py

from django.core.mail import send_mail
from django.db.models.signals import post_save

@receiver(post_save, sender=Profile)
def send_welcome_email(sender, instance, created, **kwargs):
    if created:
        send_mail(
            "Welcome",
            "Your account is created",
            "admin@example.com",
            [instance.user.email],
        )
  • Use-Case 3: Update Data Automatically

Auto Update Field Using Signal

signals.py

from django.db.models.signals import pre_save

@receiver(pre_save, sender=Profile)
def update_phone(sender, instance, **kwargs):
    if not instance.phone:
        instance.phone = "Not Provided"
  • Use-Case 4: Log Delete Activity

Post Delete Logging

signals.py

from django.db.models.signals import post_delete

@receiver(post_delete, sender=Profile)
def log_delete(sender, instance, **kwargs):
    print(f"Profile deleted: {instance.user}")
  • Use-Case 5: User Login Tracking

User Login Signal

signals.py

from django.contrib.auth.signals import user_logged_in

@receiver(user_logged_in)
def user_login_log(sender, request, user, **kwargs):
    print(f"{user.username} logged in")
  • Custom Signals

    When to Use Custom Signals?

    • Complex apps

    • App-to-app communication

    • Decoupled architecture

Create Custom Signal

signals.py

from django.dispatch import Signal

order_completed = Signal()

Send Custom Signal

views.py

from .signals import order_completed

order_completed.send(sender=None, order_id=101)

Receive Custom Signal

@receiver(order_completed)
def order_done(sender, order_id, **kwargs):
    print("Order Completed:", order_id)