How to set up user notifications for your Django app - Part 1

June 6, 2021 - by Themba Mahlangu - 6 min read

Notifications provide updates about the activity on an application. In this guide, you will learn how to set up simple notifications for your Django application. This is Part 1 of this series.

When you’re finished, you’ll be able to set up simple notifications for your Django app.

Table of Contents

Tutorials in this series:


Prerequisites


Key Terms


Step 1 - Set up your project


Install Django Notifications


Using a custom model for notifications


Create notifications based on user events


User login or logout events


Setup the signal receivers


Connect the signal receivers


Conclusion


Further reading

Tutorials in this series:

Part 1 - Setting up the backend (this tutorial)

[


Part 2 - Frontend components with TailwindCSS and AlpineJS

](https://www.advantch.com/blog/how-to-set-up-user-notifications-for-your-django-app-part-2/)

Our final product will look something like this.

Prerequisites

To complete this tutorial, you will need:

Code
Knowledge of Django

Django starter project

In this article we use
[


TailwindCSS

](https://tailwindcss.com/)
(styling) and
[


AlpineJS

](https://github.com/alpinejs/alpine)
(javascript)

LEVEL -

πŸ’»

πŸ’»

Beginner to Intermediate - Knowledge of how Django works, for example how views, URL configuration, and templates work. We will cover high-level concepts but you may need to do further reading on your own.

Key Terms

A Notification or Activity in its simplest form consists of an actor, verb, and object. It describes:

Code
an
**
 action -
**
'
*
 user signed in'
*

performed by an
**
 actor -
**
a user

on or with an
**
 object -
**
email address, or user name

Step 1 - Set up your project

Clone our
[


starter repo here

](https://github.com/advantch/simple-django-starter)
and follow the instructions to set up a new project.

Create a new app called ‘notis’ in the apps directory.

Code
 text
Code
`$ mkdir apps/notis
$ django-admin.py startapp notis `

* Our final folder structure will look like this.
*

Code
 text
Code
`project_name
β”‚   β”œβ”€β”€ config
β”‚   β”‚   β”œβ”€β”€ settings.py
β”‚   β”‚   β”œβ”€β”€ urls.py
β”‚   β”‚   └── ...
β”‚   β”œβ”€β”€ apps
β”‚   β”‚   β”œβ”€β”€ notis
β”‚   β”‚   β”‚   β”œβ”€β”€ models.py
β”‚   β”‚   β”‚   β”œβ”€β”€ apps.py
β”‚   β”‚   β”‚   └── ...
β”‚   β”‚   └── users
β”‚   β”‚       β”œβ”€β”€ signals.py
β”‚   β”‚       └── ...
β”‚   β”œβ”€β”€ templates
β”‚   β”‚   └── ... # see part 2 for this
β”‚   └── manage.py
└── requirements.txt
`
Code
This structure represents a Django project with a
`
 notis
`
app for handling notifications and a
`
 users
`
app for handling user-related functionality.

The
`
 notis
`
app contains a custom
`
 Notification
`
model as described in the document.

The
`
 users
`
app contains signal handlers for user login and logout events. The
`
 requirements.txt
`
file is at the root of the project and contains the project dependencies, including
`
 django-notifications-hq
`
.

The
`
 templates
`
directory will be populated in part 2 of the tutorial series.

Install Django Notifications

We will be using the excellent
[


Django notifications library

](https://github.com/django-notifications/django-notifications)
to do some of the heavy lifting for us.

Code
 text
Code
`# requirements.txt
# ...
django-notifications-hq==1.6.0
# ...`
Code
 python
Code
`# settings.py
INSTALLED_APPS = (
    'django.contrib.auth',
    # ...other apps,
    'notifications',
    # ...
)`
Code
 python
Code
`
from django.urls import path, include
import notifications.urls

urlpatterns = [
    # ...
    path('inbox/notifications/', include(notifications.urls, namespace='notifications')),
    # ...
]`


Notes

The package will take care of:

Code
Setting up a model to store our notifications. The model comes with the basic fields to store information about

 <actor> <verb> <action_object> <target> <time>

.

Provides a
[


manager

](https://docs.djangoproject.com/en/3.2/topics/db/managers/)
with the required business logic to handle typical actions on notifications e.g. filtering, mark as read etc.

Code
Signal dispatcher to simplify creating notifications.

Views and template tags to render notifications on your frontend Django templates or single-page app.

Using a custom model for notifications

The above should be sufficient for most apps. However, if you need to customize the notification model in order to extend the functionality you would create a new model:

Code
 python
Code
`from django.db import models 
from notifications.base.models import AbstractNotification 

class Notification(AbstractNotification): 
    # custom field example 
    category = models.ForeignKey('myapp.Category', on_delete=models.CASCADE) 

    class Meta(AbstractNotification.Meta): 
        abstract = False
`
Code
created a new app called
`
 'notis'
`
to handle extensions to the base library. Technically the model could be added to any other app. This is more organized as it keeps your notifications logic separate from your other apps.

created a new model and used
[


django’s model inheritance

](https://docs.djangoproject.com/en/3.2/topics/db/models/#model-inheritance)
to extend an existing model. You will note that we explicitly set abstract = False in the inner Meta class. Django actually does this for you, we have included it here to (hopefully) ignite your curiosity so you can gain a better understanding of how django’s model inheritance works.

Code
 text
Code
`.. 
NOTIFICATIONS_NOTIFICATION_MODEL = 'apps.notis.Notification'`
Code
We are using another model for Notifications. We should update our settings file to reflect this.

Create notifications based on user events

Let’s go through an example of how we can use this on a real application to store user sign-in and sign-out events and display them to the user.

A user story is an informal, natural language description of features of a software system (
[


Wikipedia

](https://en.wikipedia.org/wiki/User_story#:~:text=In%20software%20development%20and%20product,digitally%20in%20project%20management%20software)
). An example user story for this would be, “as a user, I want to be able to see my sign-in activity”.

Breaking it down into actionable tasks

Code
a) Listen for a user login or logout actions and store them on the database

b) Create frontend component to display notifications (Part 2)

c) Connect our frontend component to the backend. (Part 2)

User login or logout events

We need to find a way to get notified when certain actions occur. Fortunately, we don’t have to look too far, Django provides a
* signal dispatcher
* for just this purpose. You can read more about it
[


here

](https://docs.djangoproject.com/en/3.2/topics/signals/)
.

Additionally, the Django auth framework already provides prebuilt signals for login and logout actions that our code can listen to.

Setup the signal receivers

Code
 python
Code
`from django.contrib.auth import user_logged_in, user_logged_out 
from notifications.signals import notify 
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _

@receiver(user_logged_in) 
def user_signed_in(sender, user, **kwargs): 
    notify.send(user, recipient=user, verb=_("You signed in")) 

@receiver(user_logged_out) 
def user_signed_out(sender, user, **kwargs): 
    notify.send(user, recipient=user, verb=_("You signed out")) 
`

* Notes
*

Code
We created two receiver functions and connected them to the
`
 user_logged_in
`
&
`
 user_logged_out
`
signals using the @receiver decorator.

We added business logic to create a notification instance whenever the signal is received.
`
 notify.send
`
is a signal provided by the Django-notifications library. The actor recipient is the user.

Behind the scenes, the Django-notifications library will create a notification instance when the signal is dispatched.

Connect the signal receivers

Code
 python
Code
`# notis/apps.py
from django.apps import AppConfig

class NotisConfig(AppConfig): 
    name = "apps.notis" 
    def ready(self): 
        try: 
            import apps.notis.signals 
        except ImportError: 
            pass
`
Code
Signal receivers are connected in the
`
 ready()
`
method of your application configuration class. This process happens after the app registration process.
[


See the docs

](https://docs.djangoproject.com/en/3.2/topics/signals/#connecting-receiver-functions)
for a more technical explanation.

Conclusion

That’s it for this tutorial. We covered how to set up the backend to handle notifications for our Django app. In the next article, we will create frontend components and connect them to the backend.

Further reading

[


How to create Django signals

](https://simpleisbetterthancomplex.com/tutorial/2016/07/28/how-to-create-django-signals.html)
- A good article to get the basics of how the dispatch framework works

[


Activity Streams

](https://activitystrea.ms/specs/atom/1.0/)
- Definitions for the terms used in describing a Notification/Activity