Sunday, December 29, 2024
Google search engine
HomeLanguagesHow to Create and Use Signals in Django ?

How to Create and Use Signals in Django ?

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 Receiver 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)

Dominic Rubhabha-Wardslaus
Dominic Rubhabha-Wardslaushttp://wardslaus.com
infosec,malicious & dos attacks generator, boot rom exploit philanthropist , wild hacker , game developer,
RELATED ARTICLES

Most Popular

Recent Comments