Learn Django Signals | The Quickest and Easiest Way for Beginners

In this post, you are going to learn about Django Signals using real-life examples. And by the end of this tutorial, you have a good understanding of what Django Signals are and their applications.

Table of Contents

While working with large multiple tables were each table share one-to-one or many-to-many which are inter-connected
to each other as a programmer change a simple way must by manually updating dependent fields. But this can be a tidies task to achieve.

For Example:

Let us consider two tables user, profile the user share a one-to-one relationship with the profile table which has date_of_birth, age, address as fields.
While updating or creating users we must also create/update profiles and this has to be done everywhere were user details get updated.
Hence insisted on rewriting the same code. We can make use of Django signals.

Model Signals

Django Signals trigger event application whenever the model gets created, updated, or deleted in this way we can manage logic by minimum code.
We have a blogs table and we’ll be using this as an example below.

Create Model models.py and migrate it to the database

class BlogModel(models.Model):

    BLOG_STATUS = (
        ('PUBLISH', 'Publish'),
        ('DRAFT', 'Draft'),
    )

    blog_id = models.AutoField(primary_key=True)
    user = models.ForeignKey( User, on_delete=models.CASCADE, related_name='blogs' )
    title = models.CharField(max_length=255)
    content = models.TextField(blank=True, null=True)
    status = models.CharField(max_length=7, choices=BLOG_STATUS)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta():
        db_table = 'blogs'
        verbose_name = 'Blog'
        verbose_name_plural = 'Blogs'

    def __str__(self):
        return self.title

Django provides with different Types of Signals. But in this post, we’ll be discussing types of Model Signals.

pre_init signal

This signal is called before the model __init__() is instantiated.

Arguments

  • sender: Class Name of Model.
  • args: These are a list of arguments to be passed to __init__().
  • kwargs : This is a dictionary type.

Example

@receiver(pre_init, sender=BlogModel)
def blog_pre_init_signal(sender, *args, **kwargs):
    print("blog_pre_init_signal() called")

#SHELL
>>> Blog=BlogModel()
    blog_pre_init_signal() called

post_init signal

This signal is called after model __init__() is instantiated.

Example

@receiver(post_init, sender=BlogModel)
def blog_post_init_signal(sender, *args, **kwargs):
    print("blog_post_init_signal() called")

#SHELL
>>> blog = BlogModel()
    blog_pre_init_signal() called
    blog_post_init_signal() called

As in above example first it calls blog_pre_init_signal() called and after that blog_post_init_signal() called.

pre_save signal

This signal gets called before saving or updating the instance

post_save signal

This signal gets called after saving instance. The post_save has an argument created=true when a new instance is saved and while updating created=false.

Example

@receiver(pre_save, sender=BlogModel)
def blog_pre_save_signal(sender, *args, **kwargs):
    print('---------------------------------\n')
    print('blog_pre_save_signal() called')
    print('sender : {}\n'.format(sender))
    print('args : {}\n'.format(args))
    print('kwargs : {}\n'.format(kwargs))
    print('---------------------------------\n')

@receiver(post_save, sender=BlogModel)
def blog_post_save_signal(sender, *args, **kwargs):
    print('---------------------------------\n')
    print('blog_post_save_signal() called')
    print('sender : {}\n'.format(sender))
    print('args : {}\n'.format(args))
    print('kwargs : {}\n'.format(kwargs))
    print('---------------------------------\n')

#SHELL
>>> user = User.objects.get(pk=1)
>>> print(user)
    root
>>> create_blog_kwarg = {"user":user,"title":"New Blog created","content":"Blog sample description","status":"PUBLISH"}
>>> blog=BlogModel.objects.create(**create_blog_kwarg)
    blog_pre_init_signal() called
    blog_post_init_signal() called
    ---------------------------------

    blog_pre_save_signal() called
    sender : <class 'blogs.models.BlogModel'>

    args : ()

    kwargs : {'signal': <django.db.models.signals.ModelSignal object at 0x7fb35bf62ba8>, 'using': 'default', 'update_fields': None, 'instance': <BlogModel: New Blog created>, 'raw': False}

    ---------------------------------

    ---------------------------------

    blog_post_save_signal() called
    sender : <class 'blogs.models.BlogModel'>

    args : ()

    kwargs : {'signal': <django.db.models.signals.ModelSignal object at 0x7fb35bf62c50>, 'update_fields': None, 'created': True, 'raw': False, 'instance': <BlogModel: New Blog created>, 'using': 'default'}

    ---------------------------------

pre_delete signal

This signal is called before the deleting the model instance.

post_delete signal

This signal is called after the deleting the model instance.

Example

@receiver(pre_delete, sender=BlogModel)
def blog_pre_delete_signal(sender, *args, **kwargs):
    print('---------------------------------\n')
    print('blog_pre_delete_signal() called')
    print('sender : {}\n'.format(sender))
    print('args : {}\n'.format(args))
    print('kwargs : {}\n'.format(kwargs))
    print('---------------------------------\n')

@receiver(post_delete, sender=BlogModel)
def blog_post_delete_signal(sender, *args, **kwargs):
    print('---------------------------------\n')
    print('blog_post_delete_signal() called')
    print('sender : {}\n'.format(sender))
    print('args : {}\n'.format(args))
    print('kwargs : {}\n'.format(kwargs))
    print('---------------------------------\n')
    
#SHELL
>>> blog = BlogModel.objects.get(pk=160)
    blog_pre_init_signal() called
    kwargs : {'kwargs': {}, 'args': (160, 1, 'signal 1 ', 'Signal Changed', 'PUBLISH', datetime.datetime(2019, 5, 16, 10, 5, 48, 242734, tzinfo=<UTC>), datetime.datetime(2019, 5, 27, 6, 51, 3, 915106, tzinfo=<UTC>)), 'signal': <django.db.models.signals.ModelSignal object at 0x7fca0a43b908> }
    args : ()
    blog_post_init_signal() called
>>> blog.delete()
    ---------------------------------

    blog_pre_delete_signal() called
    sender : <class 'blogs.models.BlogModel'>

    args : ()

    kwargs : {'using': 'default', 'instance': <BlogModel: signal 1 >, 'signal': <django.db.models.signals.ModelSignal object at 0x7fca0a43bcc0> }

    ---------------------------------

    ---------------------------------

    blog_post_delete_signal() called
    sender : <class 'blogs.models.BlogModel'>

    args : ()

    kwargs : {'using': 'default', 'instance': <BlogModel: signal 1 >, 'signal': <django.db.models.signals.ModelSignal object at 0x7fca0a43bd68> }

    ---------------------------------

    (1, {'blogs.BlogModel': 1, 'blogs.BlogFilesModel': 0})
For complete documentation on Django Signals visit the Official Website of Django Framework.

Conclusion

We have come to the final part of this post. Till now we have discussed types of model signals such as pre_init, post_init, pre_save, post_save, pre_delete, post_delete.
If you like this post then don’t forget to share and for any queries comment below.

Related Posts

Summary
Review Date
Reviewed Item
Learn Django Signals | The Quickest and Easiest Way for Beginners
Author Rating
51star
1star1star1star1star
Software Name
Django Web Framework
Software Name
Windows Os, Mac Os, Ubuntu Os
Software Category
Web Development