Django Signals
Signals are the pieces of code used for associating events with actions. These can be implemented by developing functions that are executed when a signal calls them. A dispatcher is used to send signals. Signals are mainly used in user management and ECommerce websites.
Some in-built signals in Django are -
-
Pre_save - this signal is sent before the model’s save method is called.
-
Post_save - this signal is sent after the model’s save method is called.
-
Pre_delete - this signal is sent before the model’s delete method is called.
-
Post_delete - this signal is sent after the model’s delete method is called.
-
Pre_init - this signal is sent before instantiating a Django model.
-
Post_init - this signal is sent after instantiating a Django model.
-
M2changed - this signal is sent when changes are made in ManyToManyField in Django model.
In this tutorial, we’ll use Django signal to create a profile instance whenever a new user is created.
Create Form
myapp/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import *
class UsersignupForm(UserCreationForm):
firstname = forms.CharField(max_length=50)
lastname = forms.CharField(max_length=50)
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'firstname', 'lastname', 'email', 'password1', 'password2']
Here, firstly we imported UserCreationForm and User, and then we have created a Django form for user registration. We have manually added firstname, lastname, email, fields in our Django form, and username and password are inbuilt fields in Django UserssignupForm.
Setup Template File
myapp/templates
{% block content %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> register </title>
</head>
<body>
<form method="POST" class="post-form">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
</body>
</html>
{% endblock content %}
We have added our form in our Django template.
Create Models
myapp/models.py
from django.db import models
from django.shortcuts import render
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(upload_to="static")
def __str__(self):
return str(User)
Here, we have imported User and as we want to take image input from the user, therefore, we imported Image from a python image library. Then, we created a Profile class and added a user and image field. OneToOneField is used when one record of a model is related to one record of another model.
Create views
myapp/views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import *
from .models import *
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import authenticate, login
def signup(request):
if request.method == 'POST':
form = UsersignupForm(request.POST)
if form.is_valid():
form.save()
return redirect('signin')
else:
form = UsersignupForm()
context = {'form': form}
return render(request, 'signup.html', context)
def signin(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username = username, password = password)
if user is not None:
form = login(request, user)
return redirect('signin')
else:
messages.info(request, f'account done not exit plz sign in')
form = AuthenticationForm()
return render(request, 'signin.html', {'form': form})
Here, we created views for Signup and Signin forms.
Add URLs
Myapp/urls.py
from django.contrib import admin
from django.urls import path
from demo import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', views.signup, name='home'),
path('signup', views.signup, name='signup'),
path('signin', views.signin, name='signin'),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
Here, we have created URLs for signup and signin pages.
Create Signals File
myapp/singals.py
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()
First we have to understand the arguments used in Django signals.py file.
-
Receiver - it is used to receive the signals.
-
Sender - it is used to send the signals.
-
Created - it is used to check whether the model is created or not.
-
Instance - it is used to create model instances.
In our signals.py file, we have created the create_profile function which runs every time whenever a user is created. As we have already mentioned post_save is is sent after the model’s save method is called. Save_profile function is used to save our already created profile.
Connect signals with app.py
myapp/app.py
from django.apps import AppConfig
class DemoConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'demo'
def ready(self):
import demo.signals
We have used the above expression to connect our signals file with our app.
Setup _init_.py
default_app_config = 'demo.apps.DemoConfig'
Here, we have registered our app.
Register Models
myapp/admin.py
from django.contrib import admin
from demo.models import *
admin.site.register(Profile)
Here, we have registered our model.
So, we have already done all the required configurations. Now, let's check whether our signals are working or not.
So, we have submitted our form now lets check our user is registered or not.
So, our user is created successfully now lets check if profile of our user is created or not.
Created successfully!