Bird
Raised Fist0
Djangoframework~5 mins

Why signals enable decoupled communication in Django

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction

Signals let parts of a Django app talk to each other without being tightly connected. This makes the app easier to change and grow.

When you want to run some code after saving a database record without changing the save method.
When you want to notify other parts of your app about an event, like a user logging in.
When you want to keep your code organized by separating event handling from main logic.
When you want to add features later without rewriting existing code.
When you want different parts of your app to react to the same event independently.
Syntax
Django
from django.db.models.signals import signal_name
from django.dispatch import receiver

@receiver(signal_name, sender=ModelName)
def function_name(sender, instance, **kwargs):
    # code to run when signal is sent

@receiver connects your function to the signal.

sender limits the signal to a specific model or source.

Examples
This runs after a Book is saved and prints its title.
Django
from django.db.models.signals import post_save
from django.dispatch import receiver
from myapp.models import Book

@receiver(post_save, sender=Book)
def book_saved(sender, instance, **kwargs):
    print(f"Book saved: {instance.title}")
This runs after any request finishes, no sender needed.
Django
from django.core.signals import request_finished
from django.dispatch import receiver

@receiver(request_finished)
def request_done(sender, **kwargs):
    print("A request finished.")
Sample Program

This example shows a signal that prints a message when an Article is saved. The signal function is separate from the Article model, so they are loosely connected.

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

class Article(models.Model):
    title = models.CharField(max_length=100)

@receiver(post_save, sender=Article)
def article_saved(sender, instance, **kwargs):
    print(f"Article '{instance.title}' was saved.")

# Simulate saving an Article instance
article = Article(title='Django Signals')
article.save()
OutputSuccess
Important Notes

Signals help keep your code clean by separating event reactions from main logic.

Be careful not to overuse signals, as too many can make debugging harder.

Always connect signals in apps.py or signals.py and import them properly to ensure they work.

Summary

Signals let parts of Django apps communicate without tight links.

This makes apps easier to maintain and extend.

Use signals to react to events like saving or deleting data.

Practice

(1/5)
1. Why do Django signals help create decoupled communication between app components?
easy
A. Because signals replace the need for models in Django
B. Because signals force components to be tightly linked for better performance
C. Because signals allow components to send and receive messages without knowing each other directly
D. Because signals automatically generate database tables

Solution

  1. Step 1: Understand what decoupled communication means

    Decoupled communication means parts work independently without direct connections.
  2. Step 2: Analyze how signals work in Django

    Signals let one part send a message and others listen and react without knowing each other.
  3. Final Answer:

    Because signals allow components to send and receive messages without knowing each other directly -> Option C
  4. Quick Check:

    Signals enable decoupling = Because signals allow components to send and receive messages without knowing each other directly [OK]
Hint: Signals let parts talk without tight links [OK]
Common Mistakes:
  • Thinking signals create database tables
  • Believing signals force tight coupling
  • Confusing signals with models
2. Which of the following is the correct way to connect a signal handler to Django's post_save signal?
easy
A. post_save.connect(my_handler, sender=MyModel)
B. post_save.send(my_handler, sender=MyModel)
C. my_handler.connect(post_save, sender=MyModel)
D. connect.post_save(my_handler, sender=MyModel)

Solution

  1. Step 1: Recall Django signal connection syntax

    The correct syntax is signal.connect(handler, sender=Model).
  2. Step 2: Match the options to this syntax

    post_save.connect(my_handler, sender=MyModel) matches the correct syntax exactly.
  3. Final Answer:

    post_save.connect(my_handler, sender=MyModel) -> Option A
  4. Quick Check:

    Signal connect syntax = post_save.connect(my_handler, sender=MyModel) [OK]
Hint: Use signal.connect(handler, sender=Model) to connect [OK]
Common Mistakes:
  • Using send() instead of connect()
  • Reversing handler and signal in connect()
  • Calling connect as a method on handler
3. Given this code snippet, what will be printed when a new Book instance is saved?
from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=Book)
def notify(sender, instance, created, **kwargs):
    if created:
        print(f"New book added: {instance.title}")

book = Book(title='Django Basics')
book.save()
medium
A. No output
B. New book added: Django Basics
C. Error: receiver not connected
D. New book added: None

Solution

  1. Step 1: Understand the signal and receiver setup

    The @receiver decorator connects notify to post_save for Book.
  2. Step 2: Analyze what happens on book.save()

    Since created is True for a new instance, the print statement runs with the book title.
  3. Final Answer:

    New book added: Django Basics -> Option B
  4. Quick Check:

    post_save with created=True prints title = New book added: Django Basics [OK]
Hint: post_save with created=True triggers print [OK]
Common Mistakes:
  • Assuming no output without explicit call
  • Confusing created flag meaning
  • Forgetting @receiver decorator effect
4. Identify the error in this signal handler code that prevents it from working correctly:
from django.db.models.signals import pre_delete

def cleanup(sender, instance):
    print(f"Cleaning up {instance}")

pre_delete.connect(cleanup)
medium
A. connect() requires a sender argument
B. Signal should be post_delete instead of pre_delete
C. Handler function must be a class method
D. Missing **kwargs parameter in handler function

Solution

  1. Step 1: Check handler function signature

    Django signal handlers must accept **kwargs to avoid errors.
  2. Step 2: Verify the handler parameters

    The handler lacks **kwargs, so it will raise an error when called.
  3. Final Answer:

    Missing **kwargs parameter in handler function -> Option D
  4. Quick Check:

    Handler needs **kwargs = Missing **kwargs parameter in handler function [OK]
Hint: Always include **kwargs in signal handlers [OK]
Common Mistakes:
  • Omitting **kwargs in handler parameters
  • Thinking sender argument is always required in connect()
  • Confusing pre_delete and post_delete signals
5. You want to send a custom signal when a user completes a profile update, but you want to keep your app decoupled from the profile update logic. Which approach best uses Django signals to achieve this?
hard
A. Define a custom signal and send it inside the profile update function; connect receivers elsewhere to react
B. Call all receiver functions directly inside the profile update function
C. Modify the profile update function to import and call receivers explicitly
D. Use a global variable to track profile updates and check it in other parts

Solution

  1. Step 1: Understand decoupling goal

    Decoupling means the profile update code should not know about who reacts to the event.
  2. Step 2: Analyze options for decoupled communication

    Sending a custom signal inside the update function and connecting receivers elsewhere keeps components independent.
  3. Final Answer:

    Define a custom signal and send it inside the profile update function; connect receivers elsewhere to react -> Option A
  4. Quick Check:

    Custom signal sending keeps decoupling = Define a custom signal and send it inside the profile update function; connect receivers elsewhere to react [OK]
Hint: Send custom signals; connect receivers separately [OK]
Common Mistakes:
  • Calling receivers directly, causing tight coupling
  • Using global variables instead of signals
  • Importing receivers inside update logic