Correct understanding and use of Django signal of Signals

  • 2021-10-27 08:03:35
  • OfStack

A Simple Example of Directory Django Signal Using Django Signal to Realize Linkage Update of Different Models Django Commonly Used Built-in Signals How to Correctly Place Django Signal Monitoring Function Code
Summary

Django provides a "signal distributor" mechanism that allows decoupled applications to be notified of operations elsewhere in the framework. Generally speaking, the working principle of Django signal is that when an event occurs, a signal (signals) will be sent, and the function (receivers) that listens for this signal will be executed immediately. There are many application scenarios for Django signal, especially for linkage between different models or programs. Common examples include creating an UserProfile object instance with a 1-to-1 relationship when creating an User object instance, or triggering an email to an administrator whenever a user places an order. Today on this site, I will share how to use the Django signal correctly (signals).

A Simple Example of Django Signal

Suppose we have an User model like this, and we want to print out the prompt message of new user registration every time an User object is newly created, which can be easily realized by using Django signal (signals). Our signaler, sender, is an User model and signals whenever the User model performs an post_save action. At this time, our custom create_user function 1 will be executed once it listens to the post_save signal sent by User. First, it will judge whether the object is newly created or updated through if created; If the object is newly created, a prompt message will be printed.

# models.py


from django.db import models

from django.db.models import signals
from django.dispatch import receiver

class User(models.Model):
    name = models.CharField(max_length=16)
    gender = models.CharField(max_length=32, blank=True)

def create_user(sender, instance, created, **kwargs):

    if created:

        print("New user created!")

post_save.connect(create_user, sender=User)

In the above example, we use the connect method of the signal (post_save) to connect the custom function with the User model of the signal sender (sender). A more common way in practical applications is to use the @ receiver decorator to connect the sender with the listener function, as shown below. @ receiver (post_save, sender=User) reads to listen to post_save signals emitted by User models.


from django.db import models

from django.db.models.signals import post_save
from django.dispatch import receiver

class User(models.Model):
    name = models.CharField(max_length=16)
    gender = models.CharField(max_length=32, blank=True)

@receiver(post_save, sender=User)
def create_user(sender, instance, created, **kwargs):

    if created:

        print("New user created!")

Using Django signal to realize linkage update of different models

Let's look at another example with a complexity of 1 point. We have an Profile model, which has a 1-to-1 relationship with User model. We want to create an Profile object instance when we create an User object instance, and not create a new Profile object when we update the User object with post_save. At this time, we can customize two listening functions, create_user_profile and save_user_profile, and listen to post_save signals from sender (User model) at the same time. Since post_save can be used to create and update models at the same time, we use the judgment of if created to distinguish it.


from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    birth_date = models.DateField(null=True, blank=True)

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
   if created:
       Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

Django commonly used built-in signal

In the previous examples, we used the post_save signal, which is sent after the model calls the save () method. Other common built-in signals for the Django include:

django.db.models.signals.pre_save & post_save is sent before or after the model calls the save () method. django.db.models.signals.pre_init & post_init is sent before or after the model calls the _init_ method. django.db.models.signals.pre_delete & post_delete is sent before or after the model calls the delete () method or the query set calls the delete () method. django. db. models. signals. m2m_changed is sent after the model's many-to-many relationship changes. django.core.signals.request_started & request_finished Django is sent when an HTTP request is established or closed.

How to correctly place the monitoring function code of Django signal

In the previous case, we wrote the listening function of Django signal in models. py file. The models. py code becomes very bloated when an app has a large number of custom listeners associated with signals. A better way to focus on the user-defined signal monitoring function in the signals. py file under the corresponding folder of app, which is convenient for later centralized maintenance.

If we have an app of account, which contains User and Pofile models, we not only need to create signals. py under account folder, but also need to modify apps. py and __init___.py under account file to import the created signal listening function.

# account/signals.py


from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import User, Profile



@receiver(post_save, sender=User)

def create_user_profile(sender, instance, created, **kwargs):

  if created:

      Profile.objects.create(user=instance)



@receiver(post_save, sender=User)

def save_user_profile(sender, instance, **kwargs):

    instance.profile.save()

# account/apps.py


from django.apps import AppConfig

class AccountConfig(AppConfig):
    name = 'account'

    def ready(self):
        import account.signals

# account/__init__.py


default_app_config = 'account.apps.AccountConfig'

Summary

In this paper, we summarize the working principle of Django signal (signals), and introduce how to use Django signal to realize the linkage of models or programs. Finally, we also summarized the common built-in signals of Django and how to correctly place the custom signal listening function. Welcome to our Python Web development and Django original articles.

The above is the correct understanding and use of Django signal (Signals) details, more information about Django signal (Signals) please pay attention to other related articles on this site!


Related articles: