An in depth understanding of Django custom signals (signals)
- 2020-12-18 01:52:40
- OfStack
django has 1 custom singals that listens for 1 action and sends out notifications
Official explanation:
Django provides a "signal distributor" that allows decoupled applications to be notified when operations occur elsewhere in the framework.
Simply put, the signal allows a specific sender to notify a group of receiver that something has happened. This is useful when there are multiple pieces of code and associated with a 1 event.
django has a built-in 1 some singals in django db/models/signal py, such as
Model signals
pre_init # django the modal Automatically fires before executing its constructor
post_init # django the modal After its constructor is executed, it fires automatically
pre_save # django the modal Automatic trigger before the object is saved
post_save # django the modal When the object is saved, it is triggered automatically
pre_delete # django the modal Automatically triggered before the object is deleted
post_delete # django the modal Automatically triggered after the object is deleted
m2m_changed # django the modal The use of m2m Field operation control 3 Zhang ( add,remove,clear ) before and after, automatic trigger
class_prepared # When the program starts, detect the registered app In the modal Class, for every 1 Class, automatic trigger
Management signals
pre_migrate # perform migrate Automatic trigger before command
post_migrate # perform migrate Automatic trigger after command
Request/response signals
request_started # Automatically triggers the request before it arrives
request_finished # When the request ends, it is automatically triggered
got_request_exception # Automatically triggers after an exception is requested
Test signals
setting_changed # use test Automatically triggered when the test modifies the configuration file
template_rendered # use test Automatic trigger when testing the render template
Database Wrappers
connection_created # Automatically triggered when a database connection is created
Usage:
These singals can be used to implement some of the linkage operations in model. For example, to change the operator's log when updating records via model, you can use the post_save decorator directly in the place of operation.
Or rewrite post_save to record relevant information, 1 for good. Or, at the time of request request, record the request information.
from django.core.signals import request_finished
from django.dispatch import receiver
@receiver(request_finished)
def my_callback(sender, **kwargs):
print("Request finished!")
How do I customize singals?
a. Define the singal file
import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])
singal b. Registration
def callback(sender, **kwargs):
print("callback")
print(sender,kwargs)
pizza_done.connect(callback)
c. Trigger signal
from The path import pizza_done
pizza_done.send(sender='seven',toppings=123, size=456)
Requirements scenario:
There was a requirement in the project that when model(the library's data) was modified or deleted, it automatically triggered a synchronization task for redis (this requirement was later found to be meaningless...). , model save post_save, delete post_delete, but update is not available, and there are many scenarios using update in the code, so I searched why singals is not available.
See: https: / / code. djangoproject. com/ticket / 12184
In fact, some people have mentioned this method to the django official for a long time. Why not add it to the official version and why this pr was not accepted, please check the discussion below. Anyway, at that time, django1.9 was still not supported, so you could only write one for use first, and then remove it if there is any problem.
Solutions:
singals py file
# coding:utf-8
from django.dispatch import Signal
post_update = Signal(providing_args=["user"])
models py file
-- -- -- -- -- -- -- -- -- -- - for a model, rewrite its queryset update method of -- -- -- -- -- -- -- -- -- -- -
// Introduce custom signal file
from tools import signals
class MyCustomQuerySet(models.query.QuerySet):
def update(self, **kwargs):
super(MyCustomQuerySet, self).update(**kwargs)
//update When it's called, Send the singalsignals
signals.post_update.send(sender=self.model, user="xxx")
print("finished!")
class MyCustomManager(models.Manager):
def get_queryset(self):
return MyCustomQuerySet(self.model, using=self._db)
class crontab_ping(models.Model):
name = models.CharField(max_length=64, blank=True, null=True)
objects = MyCustomManager()
callback. py file:
-- Receive signal, trigger the operation --
from tools.signals import post_update
@receiver(post_update)
def post_update_callback(sender, **kwargs):
print(kwargs['user'])
print("post_update_success")