(Comments)
This tutorial deals with implementing event driven, decoupled logic building in Django. This kind of logic building is especially helpful where a certain function or block of code has to be run at every occurrence of a particular event. In other words, Signals help us in triggering a function or block of code to be executed when a event (or signal) is raised.
Django provides a set of built-in signals that can be piggybacked to implement certain actions. Some of the useful notifications provided are as follows:
For the complete set of built-in signals and a complete explanation of each signal, please visit the Django Documentation.
You can also define and send your own custom signals, which is explained below.
Let us assume, that your project layout is as follows:
// File Structure - project/ - project/ -__init__.py - settings.py - urls.py - myapp/ - forms.py - models.py - signals.py - tasks.py - urls.py - views.py - ... - manage.py
For the sake of example lets assume we want to run some task before saving a model by the name Users which is defined in the same app in file project/myapp/models.py. First create a receiver function. A receiver function can be any Python function or method. In our case lets call the receiver user_register_handler
# Python Code # project/myapp/tasks.py from .models import Users # importing the model from django.db.models.signals import pre_save # importing the built-in signal from django.dispatch import receiver #importing the receiver decorator @receiver(pre_save, sender=Users)# assigning the sender so it responds only before saving any object of model 'Users'. def user_register_handler(sender, **kwargs): """ do some task here """ ... ... ...
We can create our own custom signals taking advantage of the signal infrastructure.
For the sake of our example lets implement the same functionality as above using our own custom signal. First we define a signal as mentioned below
# Python Code # project/myapp/signals.py from django.dispatch import Signal user_register = Signal(providing_args=["request", "user"]) # The providing_args is a list of the names of arguments the signal will provide to listeners before saving any object of model 'Users'
The providing_args argument is purely documentational, however, as there is nothing that checks that the signal actually provides these arguments to its listeners.
For sending a signal, call either Signal.send() or Signal.send_robust(). You must provide the sender argument (which is a class most of the time) and may provide as many other keyword arguments as you like.
send() differs from send_robust() in how exceptions raised by receiver functions are handled. send() does not catch any exceptions raised by receivers; it simply allows errors to propagate. Thus not all receivers may be notified of a signal in the face of an error, whereas send_robust() catches all errors derived from Python’s Exception class, and ensures all receivers are notified of the signal. If an error occurs, the error instance is returned in the tuple pair for the receiver that raised the error.
For our case we will be using just the send() method. Also the signal is to be called (or raised) explicitly in the logic (usually from the view). So in our example we sed the signal in the register view where the user is registered just before actually populating the Users model, since we want the pre_save functionality
# Python Code # project/myapp/views.py from . import signals def register(request): ... signals.user_register.send(sender=None, request=request, user=request.user) ... """ Save the user model here """ ...
Connecting the signal to a receiver function is the same as above barring the fact that we refer our custom signal instead of the built-in pre_save signal
# Python Code # project/myapp/tasks.py from .models import Users # importing the model from .signals import user_register # importing the custom signal from django.dispatch import receiver #importing the receiver decorator @receiver(user_register, sender=Users)# assigning the sender so it responds only before saving any object of model 'Users'. def user_register_handler(sender, **kwargs): """ do some task here """ request = kwargs['request'] user = kwargs['user'] ... ...
For more detailed explanation and complete documentation, please visit the Django Documentation on Signals.
We develop web applications to our customers using python/django/angular.
Contact us at hello@cowhite.com
Comments