
Hi Dev,
In this comprehensive tutorial, you will learn how to use and create signals in Django. We'll explore how to automatically trigger actions like creating a profile when a new user is registered, using built-in signals like post_save, pre_save, and more.
This article gives you a complete guide with a working example of Django custom signals, including models, forms, views, and signals. Let's get started with Django signals step-by-step.
Django signals are used to perform actions after or before a model’s instance is saved or deleted. For example, creating a user profile immediately after a user is registered.
Types of Django Signals:
- pre_save/post_save: Triggered before/after
save()method is called. - pre_delete/post_delete: Triggered before/after
delete()method is called. - pre_init/post_init: Triggered before/after the model’s
__init__()constructor is run.
We’ll now walk through a real-world example using the post_save signal to automatically create a user profile.
Step 1: Create a Projectdjango-admin startproject exampleStep 2: Create a App
python3 manage.py startapp coreStep 3: Update setting.py
.... INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'core', ]Step 4: Create a Model
from django.db import models
from django.contrib.auth.models import User
from PIL import Image
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return f'{self.user.username} Profile'
python manage.py makemigrations python manage.py migrateStep 5: Create a Form
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email']
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['image']
Step 6: Creating the Views
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import UserRegisterForm, UserUpdateForm, ProfileUpdateForm
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Your account has been created! You can now log in.')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})
@login_required
def profile(request):
if request.method == 'POST':
u_form = UserUpdateForm(request.POST, instance=request.user)
p_form = ProfileUpdateForm(request.POST, request.FILES, instance=request.user.profile)
if u_form.is_valid() and p_form.is_valid():
u_form.save()
p_form.save()
messages.success(request, f'Your profile has been updated!')
return redirect('profile')
else:
u_form = UserUpdateForm(instance=request.user)
p_form = ProfileUpdateForm(instance=request.user.profile)
context = {
'u_form': u_form,
'p_form': p_form
}
return render(request, 'users/profile.html', context)
Step 7: Creating the signals.py File
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile
@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()
This ensures that a Profile is automatically created whenever a new User is added to the system.
core/apps.py
from django.apps import AppConfig
class CoreConfig(AppConfig):
name = 'core'
def ready(self):
import core.signals

pre_save Example:
@receiver(pre_save, sender=User)
def checker(sender, instance, **kwargs):
if instance.id:
current = instance
previous = User.objects.get(id=instance.id)
if previous.reaction != current.reaction:
# save method will continue
Connecting Signals Manually:
post_save.connect(my_function_post_save, sender=MyModel) pre_save.connect(my_function, sender=User)
FAQs - Django Signals
Q1: What are signals used for in Django?
A: Signals allow decoupled applications to get notified when actions occur elsewhere in the framework.
Q2: When should I use post_save signal?
A: Use post_save when you need to perform an action right after a model instance is saved, like creating a related profile.
Q3: Can signals slow down performance?
A: Yes, heavy logic inside signals can affect performance. Keep them light or move logic to async tasks.
Q4: How do I ensure signals run automatically?
A: Make sure you import your signals module in the apps.py using the ready() method.
Q5: Is it better to use signals or override model methods?
A: Use signals for decoupled logic. If behavior is tightly coupled with model, overriding methods is preferred.
I hope this guide helps you implement Django signals successfully in your project!
Happy Coding!