Signals

Back

Loading concept...

🎭 Django Signals: The Secret Messengers of Your App

Imagine you have a house with many rooms. When the doorbell rings, everyone in every room hears it instantlyβ€”without you running to tell each person. That’s Django Signals!


🌟 What Are Signals? (Signals Overview)

Think of signals like a magical announcement system in your Django app.

The Pizza Shop Story πŸ•

Imagine you own a pizza shop:

  • When a new order comes in, you need to:
    • Tell the kitchen to start cooking
    • Update the order board
    • Send a confirmation to the customer

Without signals: You’d have to manually call each department every single time.

With signals: The order system automatically broadcasts β€œNew Order!” and everyone who needs to know… just knows!

# This is the magic! πŸͺ„
# When something happens β†’ others react automatically

Why Signals Are Amazing

Without Signals 😫 With Signals πŸŽ‰
Code is tangled together Code is clean and separate
Hard to add new features Easy to add new reactions
One change breaks everything Changes are safe

The Three Parts of a Signal

graph TD A["πŸ“‘ SIGNAL"] --> B["Something happened!"] B --> C["🎯 SENDER"] C --> D["Who sent it?"] D --> E["πŸ‘‚ RECEIVER"] E --> F["Who listens and reacts?"]

Simple Example:

# Signal = "Doorbell rang!"
# Sender = The doorbell
# Receiver = You, running to answer

πŸ—„οΈ Model Signals: Your Database’s Announcements

Model Signals are special signals that fire when something happens to your database records.

The Library Book Story πŸ“š

Think of your database like a library:

  • pre_save = β€œI’m about to put this book on the shelf!”
  • post_save = β€œI just put this book on the shelf!”
  • pre_delete = β€œI’m about to remove this book!”
  • post_delete = β€œI just removed this book!”

The Main Model Signals

Signal When It Fires Real Example
pre_save Before saving Check if username is valid
post_save After saving Send welcome email to new user
pre_delete Before deleting Backup important data
post_delete After deleting Clean up related files

See It In Action

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

# When a new user is created...
# This function runs automatically!
def welcome_new_user(sender, instance, created, **kwargs):
    if created:  # Only for NEW users
        print(f"Welcome, {instance.username}! πŸŽ‰")

# Connect it (we'll learn this next!)
post_save.connect(welcome_new_user, sender=User)

What happens:

  1. Someone creates a new User βœ…
  2. Django saves it to database βœ…
  3. post_save signal fires πŸ“‘
  4. Your function runs automatically πŸŽ‰

The created Parameter Magic

def my_handler(sender, instance, created, **kwargs):
    if created:
        # This is a BRAND NEW record
        print("New baby was born! πŸ‘Ά")
    else:
        # This is an UPDATE to existing record
        print("Someone grew taller! πŸ“")

πŸ”Œ Connecting Signal Receivers

Now let’s learn two ways to tell Django: β€œHey, when THIS happens, run THAT function!”

Method 1: The connect() Way

Think of it like plugging in a cable:

from django.db.models.signals import post_save
from myapp.models import Order

def notify_kitchen(sender, instance, **kwargs):
    print(f"Kitchen: Start making order #{instance.id}!")

# Plug it in! πŸ”Œ
post_save.connect(notify_kitchen, sender=Order)

Method 2: The @receiver Decorator (Easier!)

Think of it like wearing a name tag that says β€œI listen to this!”

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

@receiver(post_save, sender=Order)
def notify_kitchen(sender, instance, **kwargs):
    print(f"Kitchen: Start making order #{instance.id}!")

Both do the same thing! The decorator is cleaner.

Where to Put Your Receivers? πŸ“

Best Practice: Create a signals.py file in your app:

myapp/
β”œβ”€β”€ __init__.py
β”œβ”€β”€ models.py
β”œβ”€β”€ signals.py  ← Put receivers here!
β”œβ”€β”€ apps.py     ← Connect them here!

In apps.py:

from django.apps import AppConfig

class MyappConfig(AppConfig):
    name = 'myapp'

    def ready(self):
        import myapp.signals  # Load signals!

Quick Connection Checklist

graph TD A["1. Create receiver function"] --> B["2. Add @receiver decorator"] B --> C["3. Put in signals.py"] C --> D["4. Import in apps.py ready"] D --> E["βœ… Signal connected!"]

✨ Custom Signals: Create Your Own Announcements!

Sometimes Django’s built-in signals aren’t enough. You want to broadcast YOUR own messages!

The School Bell Story πŸ””

Your school has different bells:

  • Morning bell = Class starts
  • Lunch bell = Time to eat
  • Fire alarm = Everyone evacuate!

Django gives you built-in bells. Custom signals let you create YOUR OWN bells!

Creating a Custom Signal

# signals.py
from django.dispatch import Signal

# Create your own signal! πŸŽ‰
order_completed = Signal()

# What data will it carry?
# You decide when you send it!

Sending Your Custom Signal

from myapp.signals import order_completed

def finish_order(order):
    # Do the work...
    order.status = 'completed'
    order.save()

    # πŸ“‘ Broadcast your signal!
    order_completed.send(
        sender=order.__class__,
        order=order,
        total=order.total
    )

Receiving Your Custom Signal

from django.dispatch import receiver
from myapp.signals import order_completed

@receiver(order_completed)
def send_receipt(sender, order, total, **kwargs):
    print(f"Sending receipt for ${total}!")

@receiver(order_completed)
def update_inventory(sender, order, **kwargs):
    print("Updating stock levels...")

@receiver(order_completed)
def reward_points(sender, order, **kwargs):
    print("Adding loyalty points! ⭐")

One signal β†’ Many receivers! That’s the power!

Complete Custom Signal Example

# Step 1: Define signal
pizza_ready = Signal()

# Step 2: Create receivers
@receiver(pizza_ready)
def notify_customer(sender, pizza, **kwargs):
    print(f"Your {pizza.name} is ready! πŸ•")

@receiver(pizza_ready)
def ring_bell(sender, **kwargs):
    print("DING! πŸ””")

# Step 3: Send when ready
def bake_pizza(pizza):
    # ... baking logic ...
    pizza_ready.send(sender=Pizza, pizza=pizza)

🎯 Summary: Your Signal Superpowers

graph TD A["🎭 DJANGO SIGNALS"] --> B["πŸ“‘ Overview"] A --> C["πŸ—„οΈ Model Signals"] A --> D["πŸ”Œ Connecting"] A --> E["✨ Custom"] B --> B1["Sender β†’ Signal β†’ Receiver"] C --> C1["pre_save, post_save"] C --> C2["pre_delete, post_delete"] D --> D1["connect method"] D --> D2["@receiver decorator"] E --> E1["Signal class"] E --> E2["send method"]

Quick Reference

Want To… Use This
React before save pre_save
React after save post_save
React before delete pre_delete
React after delete post_delete
Create own signal Signal()
Connect easily @receiver
Send your signal .send()

πŸš€ You Did It!

You now understand Django Signals! Remember:

Signals = Automatic announcements

Something happens β†’ Signal fires β†’ Receivers react

No manual calling needed! πŸŽ‰

Go forth and build amazing, decoupled, clean Django applications!

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.