Advanced notifications for Django
Project description
django-whistle
Django Whistle is a Django app that provides a flexible, multi-channel notification system.
Supports web (in-app), email, and push (FCM) channels with user preferences and background job processing.
Installation
pip install django-whistle
Add to your INSTALLED_APPS:
INSTALLED_APPS = [
# ...
'whistle',
'fcm_django', # only if using push notifications
]
Run migrations:
python manage.py migrate whistle
Configuration
Events and Channels
Define notification events and enable channels in your settings.py:
from django.utils.translation import gettext_lazy as _
WHISTLE_CHANNELS = ['web', 'push', 'email']
WHISTLE_NOTIFICATION_EVENTS = (
('ORDER_PLACED', _('%(actor)s placed order %(object)s')),
('ORDER_SHIPPED', _('Your order %(object)s has been shipped')),
)
Template variables: %(actor)s, %(object)s, %(target)s
User Model Integration
Add the mixin to your User model for notification preferences and unread counts:
from whistle.mixins import UserNotificationsMixin
class User(UserNotificationsMixin, AbstractUser):
pass
URL Configuration
from django.urls import path, include
urlpatterns = [
path('notifications/', include('whistle.urls')),
]
This provides:
notifications:list- Notification list viewnotifications:settings- User preference managementnotifications:read_notification- Mark notification as read via signed hash
Middleware
Add ReadNotificationMiddleware to automatically mark notifications as read:
MIDDLEWARE = [
# ...
'whistle.middleware.ReadNotificationMiddleware',
]
The middleware provides two features:
-
URL parameter tracking - Marks a notification as read when the URL contains the
read-notificationquery parameter (configurable viaWHISTLE_URL_PARAM) with the notification ID. -
DetailView auto-marking - Automatically marks all unread notifications as read when a user views a
DetailViewof an object that is related to the notification (either asobjectortarget).
Custom Managers and Handlers
Override notification logic by creating custom managers or handlers:
# settings.py
WHISTLE_AVAILABILITY_HANDLER = "myapp.handlers.availability_handler"
WHISTLE_NOTIFICATION_MANAGER_CLASS = "myapp.managers.CustomNotificationManager"
WHISTLE_EMAIL_MANAGER_CLASS = "myapp.managers.CustomEmailManager"
Asynchronous Notifications
Enable background processing with django-rq:
# settings.py
WHISTLE_USE_RQ = True
WHISTLE_REDIS_QUEUE = 'default'
RQ_QUEUES = {
'default': {
'HOST': 'localhost',
'PORT': 6379,
'DB': 0,
}
}
All Settings Reference
| Setting | Default | Description |
|---|---|---|
WHISTLE_NOTIFICATION_EVENTS |
[] |
Tuple of (event_name, template_string) pairs |
WHISTLE_CHANNELS |
['web', 'email'] |
Enabled notification channels |
WHISTLE_AVAILABILITY_HANDLER |
None |
Path to custom availability function |
WHISTLE_URL_HANDLER |
None |
Path to custom URL generation function |
WHISTLE_URL_PARAM |
'read-notification' |
Query parameter for marking notifications read |
WHISTLE_CACHE_TIMEOUT |
DEFAULT_TIMEOUT |
Cache duration (Django's default) |
WHISTLE_USE_RQ |
True |
Enable background job processing |
WHISTLE_REDIS_QUEUE |
'default' |
Redis queue name for background jobs |
WHISTLE_SIGNING_KEY |
SECRET_KEY |
Key for signing notification hashes |
WHISTLE_SIGNING_SALT |
'whistle' |
Salt for signing notification hashes |
WHISTLE_AUTH_USER_MODEL |
AUTH_USER_MODEL |
Custom user model |
WHISTLE_OLD_THRESHOLD |
None |
Age threshold for old notifications (timedelta) |
WHISTLE_DEFAULT_NOTIFICATIONS |
{} |
Default channel/event settings |
WHISTLE_NOTIFICATION_MANAGER_CLASS |
'whistle.managers.NotificationManager' |
Custom notification manager |
WHISTLE_EMAIL_MANAGER_CLASS |
'whistle.managers.EmailManager' |
Custom email manager |
Usage
Sending Notifications
from whistle.helpers import notify
notify(
recipient=user,
event='ORDER_PLACED',
actor=request.user,
object=order,
target=None,
details='Additional context',
)
Email Templates
Create event-specific email templates at templates/whistle/mails/{event_name}.txt.
Falls back to templates/whistle/mails/new_notification.txt.
Management Commands
# Delete old notifications
python manage.py delete_old_notifications [--dry-run]
# Copy notification settings between channels
python manage.py copy_channel_settings <from_channel> <to_channel> [--delete]
REST API
If using Django REST Framework, the package provides:
NotificationViewSet- Read-only viewset for user notificationsMarkNotificationsAsReadAPIView- PATCH endpoint to mark notifications as read
Managers
NotificationQuerySet
Custom queryset with filtering methods for notifications:
| Method | Description |
|---|---|
unread() |
Filter unread notifications |
mark_as_read() |
Bulk update notifications as read |
for_recipient(user) |
Filter by recipient user |
of_object(obj) |
Filter by related object |
of_target(target) |
Filter by target object |
of_object_or_target(obj) |
Filter by either object or target |
old(threshold) |
Filter notifications older than threshold |
not_old(threshold) |
Filter notifications newer than threshold |
NotificationManager
Handles notification creation and dispatch logic. Key methods:
| Method | Description |
|---|---|
notify(recipient, event, actor, object, target, details) |
Create and dispatch notification to enabled channels |
is_channel_available(user, channel) |
Check if channel is available for user |
is_notification_enabled(user, channel, event) |
Check if notification is enabled (availability + user preferences) |
get_description(event, actor, object, target) |
Render notification text from event template |
get_push_config(notification) |
Build FCM push notification configuration |
push_notification(notification) |
Send push notification via FCM |
mail_notification(notification) |
Trigger email notification |
Signals emitted:
notification_emailed- Sent after email notification is dispatchednotification_pushed- Sent after push notification is dispatched
EmailManager
Handles email notification rendering and sending:
| Method | Description |
|---|---|
send_mail(recipient, event, **kwargs) |
Send email notification (sync or via RQ) |
prepare_email(recipient, event, **kwargs) |
Build email subject, message, and HTML content |
load_template(template_type, recipient, event) |
Load event-specific or default template |
get_mail_subject(context) |
Generate subject with site name prefix |
get_mail_context(recipient, event, **kwargs) |
Build template context with descriptions |
Background Jobs
When WHISTLE_USE_RQ=True, notifications and emails are processed asynchronously via django-rq:
| Job | Description |
|---|---|
notify_in_background(recipient, event, ...) |
Queue notification creation |
send_mail_in_background(subject, message, ...) |
Queue email sending |
Jobs are dispatched to the queue specified by WHISTLE_REDIS_QUEUE (default: 'default').
Versioning
We use SemVer for versioning.
Authors
- Erik Telepovský - Pragmatic Mates
See also the list of contributors.
License
This project is licensed under the BSD License - see the LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file django_whistle-7.0.0.tar.gz.
File metadata
- Download URL: django_whistle-7.0.0.tar.gz
- Upload date:
- Size: 24.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
07feb66b3f7b4bcb7b94108bc190cc5111becdc316d740fb05fd15e898251a1d
|
|
| MD5 |
93d5897aea838c8755fad102bcc481e0
|
|
| BLAKE2b-256 |
52f9aacc9d241a0c49bcb9c240daae8aa0835232441529866d4e900fd0592668
|