Recently, I have encountered the use of django
Semaphore , Therefore, the use of signal correlation is summarized .
Django There's a built-in Signal scheduler
, It can help applications to be notified when certain fixed operations occur elsewhere in the framework . In short : Signals allow certain transmitters to notify a group of receivers that certain operations have occurred . When the receiver receives this notification, it can respond .
When the model is initialized
Model save() Method correlation signal
Model delete() Method correlation signal
Model many to many (manytomanyField) When the field changes
Before performing the migration
Use Signal.connect() Method to register a receiver function , Call the receiver when sending a signal . All receiver functions of the signal will be called one by one in the order of registration .
Signal.connect(receiver, sender=None, weak=True, dispatch_uid=None)
Let's define a receiver function , The accepting function can be any python Function or method :
def my_callback(sender, **kwargs):
print('hello world')
Be careful ️: This function accepts a sneder Parameters and keyword parameters (**kwargs), All signal handlers must accept these parameters .
Django There are two ways to connect a receiver to a signal .
Mode one :Signal.connet(my_callback)
from django.core.signals import request_finished
request_finished.connect(my_callback)
Mode two :receiver(sigal)
from django.core.signals import request_finished
from django.dispatch import receiver
@receiver(request_finished)
def my_callback(sender, **kwargs):
print('hello world')
You can get there in both ways my_callback The function is called each time a request is completed
In some cases, some signals are sent many times , But you are only interested in some of these signals . Suppose we have User
as well as Enterprise
Two model We just want to accept it as a model User
Saved signal , The code is as follows :
from django.db.models.signals import post_save
from django.dispatch import receiver
from . models import User
@receiver(post_save, sender=Udser)
# there instance Can be represented as a model instance of the current change
def my_handel(sender, instance, **kwargs):
# to do ...
In some cases , The receiver may receive the same signal several times at the same time , This may cause the receiving function to be registered multiple times , Therefore, the time of a signal is called many times , In order to prevent the same signal from being accepted many times , We can pass a unique identifier as dispatch_uid Parameter to identify the receiver function . This identifier is usually a string , For each unique dispatch_uid value , The receiver function value is bound to the signal once :
from django.core.signals import post_save
post_save.connect(my_callback, dispatch_uid='my_unique_identifier')
Suppose we have a User Model , When our user name changes, it needs to be reset token, At this time, we just need to monitor User in token Change or not , Reset if changed token, Use signals to achieve this requirement
# The user model
class User(models.Model):
id = models.BigIntegerField(primary_key=True)
name = models.CharField(max_length=32, verbose_name=' user name ')
areaCode = models.CharField(max_length=10, blank=True, verbose_name=' Mobile area code ')
phone = models.CharField(max_length=20, verbose_name=' User's mobile phone number ', blank=True)
email = models.EmailField(max_length=50, verbose_name=' User mailbox ', blank=True)
avatar = models.CharField(max_length=255, verbose_name=' The avatars ')
token = models.CharField(max_length=50, verbose_name='token')
# Semaphores realize the above scenarios
from django.db.models.signals import post_init, post_save
from django.dispatch import receiver
from . models import User
@receiver(post_init, sender=User)
def init_signal(sender, instance, **kwargs):
# When the model is initialized name Assign a value to __origin_name
instance.__origin_name = instance.name
@receiver(post_save, sender=User)
def save_signal(sender, instance, **kwargs):
# When the model is saved, view the name and __origin_name Whether it is equal or not , If not, reset token
if instance.__origin_name and instance.__origin_name != instance.name:
# Reset token