Skip to content
Related Articles

Related Articles

Improve Article

How to Create and Use Signals in Django ?

  • Last Updated : 16 Mar, 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.

  1. pre_save/post_save: This signal  works before/after the method save().
  2. pre_delete/post_delete: This signal  works before after delete a model’s instance (method delete()) this signal is thrown.
  3. 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 ?



How to use Signals ion 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 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'

Views.py

Python3




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 are now able to 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 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 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']

Signals.py(Using receiver method)

Python3




# code
from django.db.models.signals import post_save, pre_delete
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()

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 using Reciever Method – 

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




# code
from django.db.models.signals import post_save, pre_delete,pre_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .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)

 Attention geek! Strengthen your foundations with the Python Programming Foundation Course and learn the basics.  

To begin with, your interview preparations Enhance your Data Structures concepts with the Python DS Course. And to begin with your Machine Learning Journey, join the Machine Learning – Basic Level Course




My Personal Notes arrow_drop_up
Recommended Articles
Page :