How to Create and Use Signals in Django ?

07 Oct, 2021
Signals are used to perform any action on modification of a model instance. The signals are utilities that help us to connect events with actions. We can develop a function that will run when a signal calls it. In other words, Signals are used to perform some action on modification/creation of a particular entry in Database. For example, One would want to create a profile instance, as soon as a new user instance is created in Database
There are 3 types of signal.
pre_save/post_save: This signal  works before/after the method save().pre_delete/post_delete: This signal  works before after delete a model’s instance (method delete()) this signal is thrown.pre_init/post_init: This signal is thrown before/after instantiating a model (__init__() method).
pre_save/post_save: This signal  works before/after the method save().
pre_delete/post_delete: This signal  works before after delete a model’s instance (method delete()) this signal is thrown.
pre_init/post_init: This signal is thrown before/after instantiating a model (__init__() method).
    Refer to the following articles to check how to create a project and an app in Django.
       How to Create a Basic Project using MVT in Django?
       How to Create an App in Django ?
For example, if we want to create a profile of a user as soon as the user is created using post_save signal
Models.py
Python3
from django.db import modelsfrom django.contrib.auth.models import Userfrom 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'
Views.py
Python3
from django.shortcuts import render, redirectfrom django.contrib import messagesfrom django.contrib.auth.decorators import login_requiredfrom .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 are now able to log in')            return redirect('login')    else:        form = UserRegisterForm()    return render(request, 'users/register.html', {'form': form})  @login_requireddef 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 account 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)
Forms.py
Python3
from django import formsfrom django.contrib.auth.models import Userfrom django.contrib.auth.forms import UserCreationFormfrom .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']
Signals.py(Using receiver method)
Python3
# codefrom django.db.models.signals import post_save, pre_deletefrom django.contrib.auth.models import Userfrom django.dispatch import receiverfrom .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()
 
 
You can get confused from this piece of code if you are new to Django, So what is happening is when the User model is saved, a signal is fired called create_profile which creates a Profile instance with a foreign key pointing to the instance of the user. The other method save_profile just saves the instance.
 
Now let’s understand the arguments
 
receiver – The function who receives the signal and does something.
sender – Sends the signal
created — Checks whether the model is created or not
instance — created model instance
**kwargs –wildcard keyword arguments
 
Another way to connect the signal with the function:
 
You need to connect the signals file with the app.py file ready function in order to use them.
 
Python3
from django.apps import AppConfig class UsersConfig(AppConfig):    name = 'users'     def ready(self):        import users.signals
 
 
Here the signal lives.
 
If we create a user 
 
 
 Then his profile is automatically created.
 
 
You can check it in admin view too
 
 
Pre_save method is provoked just before the save function is called, Also the model is saved only after successful execution of pre_save method
 
Python3
# codefrom django.db.models.signals import post_save, pre_delete,pre_savefrom django.contrib.auth.models import Userfrom django.dispatch import receiverfrom .models import Profile  @receiver(pre_save, sender=User)def checker(sender, instance, **kwargs):    if instance.id is None:        pass    else:      current=instance      previous=User.objects.get(id=instance.id)      if previous.reaction!= current.reaction:               #save method can be called
We use this if  reaction is changed.
Using signals Connect Method
The alternative way of above method is to use connect method to fire signals.
If you just use post_save.connect(my_function), then it will get fired as soon as any save method is fired.
post_save.connect(my_function_post_save, sender=MyModel)
pre_save.connect(my_function, sender= UserTextMessage)
sagar0719kumar
Python Django
Technical Scripter 2020
Python
Technical Scripter
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
How to Install PIP on Windows ?
Python Classes and Objects
Python OOPs Concepts
Python | os.path.join() method
How to drop one or multiple columns in Pandas Dataframe
Introduction To PYTHON
How To Convert Python Dictionary To JSON?
Check if element exists in list in Python
Python | datetime.timedelta() function
Python | Get unique values from a list