How to set up user notifications for your Django app - Part 1
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.
Themba Mahlangu

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
Our final product will look something like this.
Prerequisites
To complete this tutorial, you will need:
- Knowledge of Django
- Django starter project
In this article we use TailwindCSS (styling) and AlpineJS (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:
- 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 and follow the instructions to set up a new project.
Create a new app called 'notis' in the apps directory.
$ mkdir apps/notis
$ django-admin.py startapp notis- Our final folder structure will look like this.
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.txtThis 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 to do some of the heavy lifting for us.
# requirements.txt
# ...
django-notifications-hq==1.6.0
# ...# settings.py
INSTALLED_APPS = (
'django.contrib.auth',
# ...other apps,
'notifications',
# ...
)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:
- 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 with the required business logic to handle typical actions on notifications e.g. filtering, mark as read etc.
- 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:
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 = FalseWe 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.
We created a new model and used django's 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.
..
NOTIFICATIONS_NOTIFICATION_MODEL = 'apps.notis.Notification'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). 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
- 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.
Additionally, the Django auth framework already provides prebuilt signals for login and logout actions that our code can listen to.
Setup the signal receivers
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
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
# notis/apps.py
from django.apps import AppConfig
class NotisConfig(AppConfig):
name = "apps.notis"
def ready(self):
try:
import apps.notis.signals
except ImportError:
passSignal receivers are connected in the ready() method of your application configuration class. This process happens after the app registration process. See the docs 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 - A good article to get the basics of how the dispatch framework works
Activity Streams - Definitions for the terms used in describing a Notification/Activity