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
Why signals enable decoupled communication
📖 Scenario: You are building a Django app where different parts need to react when a user registers. Instead of tightly linking code, you want a clean way to notify other parts without direct calls.
🎯 Goal: Create a Django signal setup that sends a notification when a new user is created, demonstrating how signals allow decoupled communication between app components.
📋 What You'll Learn
Create a Django model called CustomUser with a username field
Define a signal receiver function called welcome_email that listens to post_save of CustomUser
Connect the welcome_email function to the post_save signal for CustomUser
In the receiver, check if the user instance was just created and simulate sending a welcome email
💡 Why This Matters
🌍 Real World
In real Django projects, signals help different app parts respond to events like user creation, order placement, or data updates without tightly coupling code.
💼 Career
Understanding Django signals is valuable for backend developers to write clean, maintainable, and scalable web applications.
Progress0 / 4 steps
1
DATA SETUP: Create the CustomUser model
Create a Django model called CustomUser with a single field username as a CharField with max length 100.
Django
Hint
Use models.CharField(max_length=100) for the username field inside the model class.
2
CONFIGURATION: Import post_save signal and receiver decorator
Import post_save from django.db.models.signals and receiver from django.dispatch.
Django
Hint
Import post_save and receiver to prepare for signal handling.
3
CORE LOGIC: Define the signal receiver function
Define a function called welcome_email decorated with @receiver(post_save, sender=CustomUser). Inside, check if created is True and simulate sending a welcome email by assigning message = f"Welcome {instance.username}!".
Django
Hint
Use the @receiver decorator with post_save and sender=CustomUser. Check the created flag inside the function.
4
COMPLETION: Connect the signal and finalize
Ensure the welcome_email function is connected to the post_save signal for CustomUser using the @receiver decorator as done. This completes the decoupled communication setup.
Django
Hint
The @receiver decorator already connects the function to the signal. No extra code needed here.
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
Step 1: Understand what decoupled communication means
Decoupled communication means parts work independently without direct connections.
Step 2: Analyze how signals work in Django
Signals let one part send a message and others listen and react without knowing each other.
Final Answer:
Because signals allow components to send and receive messages without knowing each other directly -> Option C
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
Step 1: Recall Django signal connection syntax
The correct syntax is signal.connect(handler, sender=Model).
Step 2: Match the options to this syntax
post_save.connect(my_handler, sender=MyModel) matches the correct syntax exactly.
Final Answer:
post_save.connect(my_handler, sender=MyModel) -> Option A
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
Step 1: Understand the signal and receiver setup
The @receiver decorator connects notify to post_save for Book.
Step 2: Analyze what happens on book.save()
Since created is True for a new instance, the print statement runs with the book title.
Final Answer:
New book added: Django Basics -> Option B
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
Step 1: Check handler function signature
Django signal handlers must accept **kwargs to avoid errors.
Step 2: Verify the handler parameters
The handler lacks **kwargs, so it will raise an error when called.
Final Answer:
Missing **kwargs parameter in handler function -> Option D
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
Step 1: Understand decoupling goal
Decoupling means the profile update code should not know about who reacts to the event.
Step 2: Analyze options for decoupled communication
Sending a custom signal inside the update function and connecting receivers elsewhere keeps components independent.
Final Answer:
Define a custom signal and send it inside the profile update function; connect receivers elsewhere to react -> Option A
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]