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")


Related articles: