Django/DRF Signals: Custom Signals, Model Signals, Enforcing Business Rules

Manish Sharma
3 min readJul 9, 2023

--

Signals in Django DRF
Signals in Django Framework

This is part-4 of the DRF/Django Tutorial series.

All tutorials: Part-1 Part-2 Part-3 Part-4 Part-5 Part-6

Inspiration

Decoupling is the process of minimising dependence between two or more components. This allows one component to be changed without causing any side effect to other components, provided it adheres to the same interface.

Why should I care about decoupling?

It allows one component to be updated independent of others.

Easy testing and troubleshooting.

It allows a feature to be deployed separately.

Signals

Signals in Django allows one Django component to send notification to another in a decoupled manner. The Signal ecosystem in Django has following parts:

Signal: An object used to notify a particular event.

Sender : An object that sends the signal .

Receiver: An object that receives the signal.

How to use Signals?

Define a Signal

Define one or more receivers

Register receivers

Send signals from any component.

It is important to note that we may define our own custom signals. Django also provides Model Signals allows App components to be notified of Model events such as insert/update/delete.

Custom Signals

Defining Signal : Create a file signals.py inside project/app folder as follows:

Here we have defined a signal with three params.

Defining one or more receivers: Create a file receivers.py inside project/app folder as follows:

Once signal is received it will print a message on console. You may do whetever you want.

Registering receivers: Create a file apps.py inside project/app folder as follows:

Sending signals. We are sending signal each time a view is visited. So lets create view as follows:

The line

signals.user_visit_signal.send(sender=request ,date_time=date_time,ip=ip,device=device)

is sending signal “user_visit_signal” to registered receivers. You may check this message in terminal.

Model Signals

Django provides built in Signals for Models. Model Signals allows us to perform actions upon model creation, updation or deletion.

Django provides following model signals: pre_save, post_save, pre_delete, post_delete .

Use case

Consider business rule:

“A Profile may not be updated more than once in a day”

or

“We do not want anyone to create a Notice with title ‘Oops’ “

How can we implement this?We can implement this as follows:

Override save() method of Notice model . If title is “Opps” we are sending a custom signal “invalid_notice_signal”. We have to create a receiver for this. If insertion is successful, Django will automatically send “post_save” Model Signal to registered receivers.

Define two receivers; one for successful operation and other for unsuccessful one as follows:

That’s it. Try creating a notice using “title” and “description” parameters. if title is “Oops” it won’t succeed. If operation succeeds it will display succesful message. All that we have to do is to execute endpoint:

POST http://127.0.0.1:8000/notice/create

Please refer to this file for further explaination.

It is important to note that signals are synchronous, so the receiver executes in a synchronous manner. Thus if we have two receivers, the second receiver may execute only after the first receiver has completed execution. If you want to handle time consuming, blocking tasks; you may use combination of Celery and Redis for this purpose.

Please refer to this github repo for source code.
Happy Coding.

--

--