Name | dj-notif JSON |
Version |
0.2.2
JSON |
| download |
home_page | None |
Summary | A comprehensive Django package for managing notifications with automatic dispatching, WebSocket-based real-time delivery, and category-based organization |
upload_time | 2025-08-02 15:40:53 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.10 |
license | MIT License
Copyright (c) 2025 Armin Fekri
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
|
keywords |
django
notifications
websocket
real-time
channels
jwt
broadcast
rest-api
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# Django Notification Manager (dj_notif)
[](https://badge.fury.io/py/dj-notif)
[](https://www.python.org/downloads/)
[](https://www.djangoproject.com/)
[](https://opensource.org/licenses/MIT)
[](https://github.com/Hexoder/DjangoNotification)
> ⚠️ **BETA VERSION** - This package is currently in beta. While functional, it may have breaking changes in future releases. Please test thoroughly in your development environment before using in production.
A comprehensive Django package for managing notifications with automatic dispatching and category-based organization.
## Features
- 🔔 **Real-time Notifications**: WebSocket-based instant notification delivery (live delivery active, management methods coming soon)
- 📱 **Category-based Organization**: Group notifications by type (task assignments, comments, etc.)
- 📢 **Broadcast Notifications**: Send notifications to all users with read tracking
- 🔐 **JWT Authentication**: Secure connections with JWT tokens
- 📊 **REST API**: Complete REST API for notification management
- 🎯 **Automatic Dispatching**: Notifications are automatically sent when models are saved
- 📝 **Read/Unread Tracking**: Mark notifications as read individually or by category
- 🔄 **Soft Delete**: Built-in soft delete functionality for data integrity
- 🎨 **Customizable**: Easy to extend with custom notification types
## Installation
### 1. Install the Package
```bash
pip install dj_notif
```
### 2. Add to Django Settings
Add `dj_notif` to your `INSTALLED_APPS`:
```python
INSTALLED_APPS = [
# ... other apps
'dj_notif',
]
```
### 3. Configure Channels
Add the following to your Django settings for WebSocket notification delivery:
```python
# Channels Configuration
ASGI_APPLICATION = 'your_project.asgi.application'
# Channel Layers (Redis backend recommended for production)
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
},
},
}
# JWT Settings for Authentication
CHANNEL_LAYERS_JWT_SECRET = 'your-secret-key'
```
### 4. Update ASGI Configuration
Update your `asgi.py` file to include the notification routing for WebSocket delivery:
```python
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your_project.settings')
import django
django.setup()
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from django_channels_jwt.middleware import JwtAuthMiddlewareStack
from dj_notif.routes import notification_urlpatterns
django_asgi_app = get_asgi_application()
application = ProtocolTypeRouter({
"http": django_asgi_app,
"websocket": JwtAuthMiddlewareStack(
URLRouter(
notification_urlpatterns # Add your other URL patterns here
),
),
})
```
### 5. Include URLs
Add the notification URLs to your main `urls.py`:
```python
from django.urls import path, include
urlpatterns = [
# ... other URL patterns
path('api/', include('dj_notif.urls')),
]
```
The package provides the following URL endpoints:
**User Notifications:**
- `/api/notifications/user/` - Get all user notifications
- `/api/notifications/user/categories/` - Get unread count by category
- `/api/notifications/user/mark_all_as_read/` - Mark all user notifications as read
- `/api/notifications/user/category/{category}/` - Get user notifications by category
- `/api/notifications/user/category/{category}/mark_all_read` - Mark all user notifications in category as read
- `/api/notifications/user/category/{category}/mark_read/{id}/` - Mark specific user notification as read
**Broadcast Notifications:**
- `/api/notifications/broadcast/` - Get all broadcast notifications
- `/api/notifications/broadcast/category/{category}/` - Get broadcast notifications by category
- `/api/notifications/broadcast/category/{category}/mark_read/{id}/` - Mark specific broadcast notification as read
**WebSocket:**
- `/api/notifications/ws_auth/` - WebSocket authentication endpoint (requires authentication, returns UUID)
### 6. Run Migrations
```bash
python manage.py makemigrations
python manage.py migrate
```
### 7. Register Custom Notification Models and Serializers
The package automatically discovers notification models and serializers. Ensure your custom notification models and serializers are properly imported in your Django app's `__init__.py` or `apps.py`:
```python
# In your app's apps.py
from django.apps import AppConfig
class YourAppConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'your_app'
def ready(self):
# Import your notification models and serializers to register them
from .notifications import models, serializers
```
Or in your app's `__init__.py`:
```python
# In your app's __init__.py
default_app_config = 'your_app.apps.YourAppConfig'
```
#### How Auto-Discovery Works
The package uses Django's app registry to automatically discover:
1. **Notification Models**: All classes inheriting from `BaseNotificationModel`
2. **Notification Serializers**: All classes inheriting from `BaseNotificationSerializer`
The discovery happens when Django starts up and loads all apps. Each model and serializer must have a `notification_class_name` attribute that matches between the model and its corresponding serializer.
**Important**: Make sure your notification models and serializers are imported when Django starts, otherwise they won't be discovered by the package.
## Usage
### 1. Create Custom Notification Models
Create notification models by inheriting from `BaseNotificationModel`. You can define related models using either `PositiveIntegerField` (simple ID reference) or `ForeignKey` (full relationship). This example uses ForeignKey for better relationship management:
```python
from django.db import models
from dj_notif.models import BaseNotificationModel
from your_app.models import Task
class TaskNotification(BaseNotificationModel):
class NotificationTitle(models.TextChoices):
created = 'task_created'
updated = 'task_updated'
completed = 'task_completed'
user = models.ForeignKey(User, related_name='task_notifications', on_delete=models.CASCADE)
title = models.CharField(choices=NotificationTitle.choices, max_length=20)
task = models.ForeignKey(Task, related_name='notifications', on_delete=models.SET_NULL)
notification_class_name = 'task' # Required!
```
### 2. Create Custom Serializers
Create serializers by inheriting from `BaseNotificationSerializer`:
```python
from dj_notif.serializers import BaseNotificationSerializer
from your_app.serializers import TaskSerializer
class TaskNotificationSerializer(BaseNotificationSerializer):
notification_class_name = 'task' # Must match model
task = TaskSerializer(fields=['id', 'name'])
class Meta:
model = TaskNotification
extra_fields = ['user', 'task', 'requested_user']
```
#### Broadcast Notification Serializers
For broadcast notifications, inherit from `BaseBroadcastNotificationSerializer`:
```python
from dj_notif.serializers import BaseBroadcastNotificationSerializer
class BroadcastNotificationSerializer(BaseBroadcastNotificationSerializer):
notification_class_name = 'broadcast' # Must match model
class Meta:
model = BroadcastNotification
# No extra_fields needed for broadcast notifications
```
### 3. Using Notifications in Your Code
#### Creating Notifications
```python
# Single notification
TaskNotification.objects.create(
user=user,
title=TaskNotification.NotificationTitle.created,
description=f'Task {task.name} has been created',
level=1, # 1=low, 2=medium, 3=high
task=task
)
# Multiple notifications at once
TaskNotification.create_notifications(
title='New Project Available',
description='A new project has been created',
level=2,
users=[1, 2, 3, 4] # List of user IDs
)
# Broadcast notifications (sent to all users)
BroadcastNotification.objects.create(
title=BroadcastNotification.NotificationTitle.system_notification,
description='System maintenance scheduled for tomorrow',
level=2
)
```
#### Using in Your Views or Services
```python
# In your views.py or services
def create_task_notification(user_id, task, action):
"""Create a notification when a task is created, updated, or completed"""
title_map = {
'created': TaskNotification.NotificationTitle.created,
'updated': TaskNotification.NotificationTitle.updated,
'completed': TaskNotification.NotificationTitle.completed,
}
TaskNotification.objects.create(
user=user_id,
title=title_map[action],
description=f'Task {task.name} has been {action}',
level=1,
task=task
)
# Usage example
create_task_notification(
user_id=user,
task=task,
action='created'
)
```
### 4. WebSocket Live Delivery
Notifications are automatically delivered via WebSocket when they are created. To connect to the WebSocket, you need to follow a two-step authentication process:
#### Step 1: Get WebSocket Authentication UUID
First, make a GET request to the `ws_auth` endpoint to get a UUID:
```javascript
// Get WebSocket authentication UUID
async function getWsAuthUuid() {
const response = await fetch('/api/notifications/ws_auth/', {
method: 'GET',
headers: {
'Authorization': 'Bearer your-jwt-token',
'Content-Type': 'application/json',
},
});
if (response.ok) {
const data = await response.json();
return data.uuid; // UUID for WebSocket connection
} else {
throw new Error('Failed to get WebSocket auth UUID');
}
}
```
#### Step 2: Connect to WebSocket with UUID
Use the UUID as a query parameter when connecting to the WebSocket:
```javascript
// Connect to WebSocket with authentication UUID
async function connectToWebSocket() {
try {
// Get authentication UUID
const uuid = await getWsAuthUuid();
// Connect to WebSocket with UUID
const ws = new WebSocket(`ws://localhost:8000/ws/notifications/?uuid=${uuid}`);
ws.onopen = function() {
console.log('WebSocket connected successfully');
};
ws.onmessage = function(event) {
const data = JSON.parse(event.data);
console.log('New notification:', data);
if (data.type === 'notifications') {
// Handle notification data
const notification = data.payload.notification;
// Update UI, show toast, etc.
}
};
ws.onerror = function(error) {
console.error('WebSocket error:', error);
};
ws.onclose = function() {
console.log('WebSocket connection closed');
};
return ws;
} catch (error) {
console.error('Failed to connect to WebSocket:', error);
}
}
// Usage
const wsConnection = connectToWebSocket();
```
**Note**: WebSocket methods for getting notifications and marking them as read are not yet implemented. Use the REST API endpoints for these operations.
#### Authentication Requirements
- The `ws_auth` endpoint requires `IsAuthenticated` permission
- You must include your JWT token in the Authorization header
- The returned UUID is valid for a limited time
- Use the UUID as a query parameter when connecting to the WebSocket
## Supported Notification Types
The package supports various notification types. Here are examples using ForeignKey relationships:
### Task Notifications
```python
from your_app.models import Task
class TaskNotification(BaseNotificationModel):
class NotificationTitle(models.TextChoices):
created = 'task_created'
updated = 'task_updated'
completed = 'task_completed'
user = models.ForeignKey(User, related_name='task_notifications', on_delete=models.CASCADE)
task = models.ForeignKey(Task, on_delete=models.SET_NULL)
notification_class_name = 'task'
```
### Comment Notifications
```python
from your_app.models import Comment
class CommentNotification(BaseNotificationModel):
class NotificationTitle(models.TextChoices):
mention = 'mention'
reply = 'reply'
user = models.ForeignKey(User, related_name='comment_notifications', on_delete=models.CASCADE)
comment = models.ForeignKey(Comment, on_delete=models.SET_NULL)
notification_class_name = 'comment'
```
### Custom Notifications
```python
class CustomNotification(BaseNotificationModel):
class NotificationTitle(models.TextChoices):
info = 'info'
warning = 'warning'
error = 'error'
user = models.ForeignKey(User, related_name='custom_notifications', on_delete=models.CASCADE)
custom_data = models.JSONField(default=dict) # Any additional data
notification_class_name = 'custom'
```
### Broadcast Notifications
```python
class BroadcastNotification(BaseBroadcastNotificationModel):
class NotificationTitle(models.TextChoices):
system_notification = 'system_notification'
admin_notification = 'admin_notification'
title = models.CharField(choices=NotificationTitle.choices, max_length=50)
description = models.CharField(max_length=200)
level = models.IntegerField(choices=[(1, 'Low'), (2, 'Medium'), (3, 'High')])
# user_read_at_receipts field is automatically handled by BaseBroadcastNotificationModel
notification_class_name = 'broadcast'
```
## API Endpoints
### REST API
The package provides two types of notification endpoints:
#### User Notifications
User-specific notifications that are sent to individual users. These notifications are tied to specific users and can be marked as read by the intended recipient.
#### Broadcast Notifications
System-wide notifications that are sent to all users. These notifications use a `user_read_at_receipts` JSON field to track which users have read them, allowing multiple users to mark the same notification as read.
| Endpoint | Method | Description |
|----------------------------------------------|--------|-------------|
| `/api/notifications/user/` | GET | Get all user notifications for authenticated user |
| `/api/notifications/user/categories/` | GET | Get unread count by category for user notifications |
| `/api/notifications/user/mark_all_as_read/` | POST | Mark all user notifications as read |
| `/api/notifications/user/category/{category}/` | GET | Get user notifications by category |
| `/api/notifications/user/category/{category}/mark_all_read` | POST | Mark all user notifications in category as read |
| `/api/notifications/user/category/{category}/mark_read/{id}/` | POST | Mark specific user notification as read |
| `/api/notifications/broadcast/` | GET | Get all broadcast notifications for authenticated user |
| `/api/notifications/broadcast/category/{category}/` | GET | Get broadcast notifications by category |
| `/api/notifications/broadcast/category/{category}/mark_read/{id}/` | POST | Mark specific broadcast notification as read |
| `/api/notifications/ws_auth/` | GET | WebSocket authentication endpoint |
### WebSocket Live Delivery
Notifications are automatically sent to connected clients when they are created. The WebSocket connection receives notifications in real-time without needing to send commands.
**Note**: WebSocket commands for getting notifications and marking them as read are not yet implemented. Use the REST API for these operations.
### API Usage Examples
#### User Notifications
```javascript
// Get all user notifications
const response = await fetch('/api/notifications/user/', {
headers: { 'Authorization': 'Bearer your-jwt-token' }
});
// Get unread count by category
const categories = await fetch('/api/notifications/user/categories/', {
headers: { 'Authorization': 'Bearer your-jwt-token' }
});
// Mark specific notification as read
await fetch('/api/notifications/user/category/task/mark_read/123/', {
method: 'POST',
headers: { 'Authorization': 'Bearer your-jwt-token' }
});
```
#### Broadcast Notifications
```javascript
// Get all broadcast notifications
const response = await fetch('/api/notifications/broadcast/', {
headers: { 'Authorization': 'Bearer your-jwt-token' }
});
// Get broadcast notifications by category
const systemNotifs = await fetch('/api/notifications/broadcast/category/pm_broadcast/', {
headers: { 'Authorization': 'Bearer your-jwt-token' }
});
// Mark broadcast notification as read (for current user)
await fetch('/api/notifications/broadcast/category/pm_broadcast/mark_read/456/', {
method: 'POST',
headers: { 'Authorization': 'Bearer your-jwt-token' }
});
```
## Configuration Options
### Notification Levels
```python
class NotificationLevel(models.IntegerChoices):
low = 1
medium = 2
high = 3
```
### Channel Name Format
Notifications are sent to channels in the format: `notif_user_{user_id}`
## Dependencies
- Django >= 5.2
- Django REST Framework >= 3.15.2
- Django Channels >= 4.2.0
- django-channels-jwt >= 0.0.3
- Redis (for channel layers)
## Example Project Structure
```
your_project/
├── apps/
│ └── your_app/
│ ├── notifications/
│ │ ├── __init__.py
│ │ ├── models.py # Custom notification models
│ │ └── serializers.py # Custom notification serializers
│ ├── models.py # Your main models
│ ├── signals.py # Django signals for notifications
│ ├── apps.py # App configuration
│ └── __init__.py
├── your_project/
│ ├── asgi.py # ASGI configuration with WebSocket routing
│ ├── settings.py # Django settings with channels config
│ └── urls.py # URL configuration
└── manage.py
```
### Recommended File Organization
1. **Create a `notifications/` subdirectory** in each app that needs notifications
2. **Place notification models** in `notifications/models.py`
3. **Place notification serializers** in `notifications/serializers.py`
4. **Import notifications** in your app's `apps.py` or `__init__.py`
5. **Use signals** in your main app's `signals.py` to trigger notifications
### Example App Structure
```python
# apps/your_app/notifications/__init__.py
# This file can be empty, but ensures the directory is a Python package
# apps/your_app/notifications/models.py
from dj_notif.models import BaseNotificationModel
class YourNotification(BaseNotificationModel):
# Your notification model definition
pass
# apps/your_app/notifications/serializers.py
from dj_notif.serializers import BaseNotificationSerializer
class YourNotificationSerializer(BaseNotificationSerializer):
# Your notification serializer definition
pass
# apps/your_app/apps.py
from django.apps import AppConfig
class YourAppConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'your_app'
def ready(self):
# Import to register notifications
from .notifications import models, serializers
from . import signals # Import signals to register them
```
## Best Practices
### 1. Notification Naming Conventions
- Use descriptive names for notification classes: `TaskAssignmentNotification`, `CommentMentionNotification`
- Use consistent naming for `notification_class_name`: lowercase with underscores
- Group related notifications in the same model with different titles
### 2. Signal Organization
- Keep signal handlers focused and lightweight
- Use transaction management for critical operations
- Handle exceptions gracefully to prevent signal failures
- Consider using `@receiver` decorators with `dispatch_uid` for unique signal handlers
### 3. Performance Considerations
- Use `bulk_create()` for multiple notifications when possible
- Consider using `select_related()` and `prefetch_related()` in serializers
- Implement pagination for notification lists
- Use database indexes on frequently queried fields
### 4. Security Best Practices
- Always validate user permissions before creating notifications
- Use proper authentication for WebSocket connections
- Sanitize notification content to prevent XSS attacks
- Implement rate limiting for notification creation
### 5. Testing Notifications
```python
from django.test import TestCase
from your_app.notifications.models import TaskNotification
class NotificationTestCase(TestCase):
def setUp(self):
self.user_id = 1 # Simple user ID
def test_notification_creation(self):
notification = TaskNotification.objects.create(
user=self.user_id,
title='task_created',
description='Test notification',
level=1,
task_id=123
)
self.assertEqual(notification.user, self.user_id)
self.assertEqual(notification.title, 'task_created')
self.assertEqual(notification.task_id, 123)
def test_notification_dispatch(self):
# Test that notifications are dispatched when saved
with self.assertNumQueries(1): # Adjust based on your setup
notification = TaskNotification.objects.create(
user=self.user_id,
title='task_created',
description='Test notification',
level=1,
task_id=123
)
```
## Troubleshooting
### Common Issues
1. **WebSocket Connection Fails**
- Ensure Redis is running
- Check JWT token validity
- Verify ASGI configuration
2. **Notifications Not Sending**
- Check channel layer configuration
- Ensure `notification_class_name` is set in models
- Verify serializer registration
3. **Migration Errors**
- Run `python manage.py makemigrations dj_notif`
- Ensure all custom notification models are in `INSTALLED_APPS`
### Debug Mode
Enable debug logging in settings:
```python
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'notification': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}
```
## Deployment
### Production Considerations
1. **Redis Configuration**
```python
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('your-redis-host', 6379)],
"capacity": 1500, # Maximum number of messages in a channel
"expiry": 10, # Message expiry in seconds
},
},
}
```
2. **ASGI Server**
- Use Daphne or Uvicorn for production
- Configure proper worker processes
- Set up load balancing for WebSocket connections
3. **Security**
- Use HTTPS/WSS in production
- Configure proper CORS settings
- Implement rate limiting
- Use secure JWT secrets
4. **Monitoring**
- Monitor Redis memory usage
- Track WebSocket connection counts
- Set up alerts for notification failures
- Log notification delivery rates
### Docker Deployment
```dockerfile
# Example Dockerfile
FROM python:3.11
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
# Option 1: Using Daphne (ASGI server for WebSocket support)
CMD ["daphne", "-b", "0.0.0.0", "-p", "8000", "your_project.asgi:application"]
# Option 2: Using Gunicorn with Uvicorn (ASGI server for WebSocket support)
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--worker-class", "uvicorn.workers.UvicornWorker", "your_project.asgi:application"]
```
### Environment Variables
```bash
# Required environment variables
REDIS_URL=redis://your-redis-host:6379
CHANNEL_LAYERS_JWT_SECRET=your-secret-key
DJANGO_SECRET_KEY=your-django-secret
# Optional
REDIS_CAPACITY=1500
REDIS_EXPIRY=10
```
## Migration and Upgrades
### Upgrading from Previous Versions
When upgrading the package, follow these steps:
1. **Backup your database** before running migrations
2. **Update the package**: `pip install --upgrade dj_notif`
3. **Run migrations**: `python manage.py migrate`
4. **Test your notification system** thoroughly
5. **Update your code** if any breaking changes are introduced
### Breaking Changes
Check the [CHANGELOG.md](CHANGELOG.md) file for detailed information about breaking changes between versions.
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests
5. Submit a pull request
### Development Setup
```bash
# Clone the repository
git clone https://github.com/your-username/dj_notif.git
cd dj_notif
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install development dependencies
pip install -e .
pip install -r requirements-dev.txt
# Run tests
python manage.py test dj_notif
```
## License
This project is licensed under the MIT License - see the LICENSE file for details.
## Support
For support and questions, please open an issue on the GitHub repository or contact the maintainer.
## Changelog
### Version 0.2.0 (Latest)
- ✨ **Broadcast Notifications**: Added support for system-wide notifications sent to all users
- 🔄 **Separate ViewSets**: Split user notifications and broadcast notifications into separate ViewSets
- 📊 **Enhanced API Structure**: Reorganized API endpoints with `/user/` and `/broadcast/` prefixes
- 🎯 **Multi-user Read Tracking**: Broadcast notifications use `user_read_at_receipts` JSON field for read status
- 🔧 **Improved URL Routing**: Better organized URL structure for different notification types
- 📝 **BaseBroadcastNotificationModel**: New base model for broadcast notifications
- 📝 **BaseBroadcastNotificationSerializer**: New base serializer for broadcast notifications
- 🚀 **Auto-discovery Support**: Broadcast notifications work with the existing auto-discovery system
### Version 0.1.0
- 🎉 **Initial release**
- 🔔 **WebSocket-based real-time notifications**: Live notification delivery via WebSocket connections
- 📊 **REST API for notification management**: Complete CRUD operations for notifications
- 🔐 **JWT authentication support**: Secure authentication for both REST API and WebSocket connections
- ⚡ **Automatic notification dispatching**: Notifications are automatically sent when models are saved
- 📱 **Category-based notification organization**: Group notifications by type (task assignments, comments, etc.)
- 🔄 **Soft delete functionality**: Built-in soft delete for data integrity
- 🎨 **Customizable notification types**: Easy to extend with custom notification models and serializers
- 🔍 **Auto-discovery system**: Automatic discovery of notification models and serializers
- 📈 **Read/unread tracking**: Mark notifications as read individually or by category
- 🌐 **WebSocket authentication**: Secure WebSocket connections with JWT token validation
Raw data
{
"_id": null,
"home_page": null,
"name": "dj-notif",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": "Armin Fekri <armiin.fekri1@gmail.com>",
"keywords": "django, notifications, websocket, real-time, channels, jwt, broadcast, rest-api",
"author": null,
"author_email": "Armin Fekri <armiin.fekri1@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/c9/e1/77415df6f3f5c67d92d04aa3604fd2014d8fcc43b4cb628e4dbe19196ec6/dj_notif-0.2.2.tar.gz",
"platform": null,
"description": "# Django Notification Manager (dj_notif)\n\n[](https://badge.fury.io/py/dj-notif)\n[](https://www.python.org/downloads/)\n[](https://www.djangoproject.com/)\n[](https://opensource.org/licenses/MIT)\n[](https://github.com/Hexoder/DjangoNotification)\n\n> \u26a0\ufe0f **BETA VERSION** - This package is currently in beta. While functional, it may have breaking changes in future releases. Please test thoroughly in your development environment before using in production.\n\n\n\nA comprehensive Django package for managing notifications with automatic dispatching and category-based organization.\n\n## Features\n\n- \ud83d\udd14 **Real-time Notifications**: WebSocket-based instant notification delivery (live delivery active, management methods coming soon)\n- \ud83d\udcf1 **Category-based Organization**: Group notifications by type (task assignments, comments, etc.)\n- \ud83d\udce2 **Broadcast Notifications**: Send notifications to all users with read tracking\n- \ud83d\udd10 **JWT Authentication**: Secure connections with JWT tokens\n- \ud83d\udcca **REST API**: Complete REST API for notification management\n- \ud83c\udfaf **Automatic Dispatching**: Notifications are automatically sent when models are saved\n- \ud83d\udcdd **Read/Unread Tracking**: Mark notifications as read individually or by category\n- \ud83d\udd04 **Soft Delete**: Built-in soft delete functionality for data integrity\n- \ud83c\udfa8 **Customizable**: Easy to extend with custom notification types\n\n## Installation\n\n### 1. Install the Package\n\n```bash\npip install dj_notif\n```\n\n### 2. Add to Django Settings\n\nAdd `dj_notif` to your `INSTALLED_APPS`:\n\n```python\nINSTALLED_APPS = [\n # ... other apps\n 'dj_notif',\n]\n```\n\n### 3. Configure Channels\n\nAdd the following to your Django settings for WebSocket notification delivery:\n\n```python\n# Channels Configuration\nASGI_APPLICATION = 'your_project.asgi.application'\n\n# Channel Layers (Redis backend recommended for production)\nCHANNEL_LAYERS = {\n 'default': {\n 'BACKEND': 'channels_redis.core.RedisChannelLayer',\n 'CONFIG': {\n \"hosts\": [('127.0.0.1', 6379)],\n },\n },\n}\n\n# JWT Settings for Authentication\nCHANNEL_LAYERS_JWT_SECRET = 'your-secret-key'\n```\n\n### 4. Update ASGI Configuration\n\nUpdate your `asgi.py` file to include the notification routing for WebSocket delivery:\n\n```python\nimport os\nos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your_project.settings')\nimport django\ndjango.setup()\n\nfrom django.core.asgi import get_asgi_application\nfrom channels.routing import ProtocolTypeRouter, URLRouter\nfrom django_channels_jwt.middleware import JwtAuthMiddlewareStack\nfrom dj_notif.routes import notification_urlpatterns\n\ndjango_asgi_app = get_asgi_application()\n\napplication = ProtocolTypeRouter({\n \"http\": django_asgi_app,\n \"websocket\": JwtAuthMiddlewareStack(\n URLRouter(\n notification_urlpatterns # Add your other URL patterns here\n ),\n ),\n})\n```\n\n### 5. Include URLs\n\nAdd the notification URLs to your main `urls.py`:\n\n```python\nfrom django.urls import path, include\n\nurlpatterns = [\n # ... other URL patterns\n path('api/', include('dj_notif.urls')),\n]\n```\n\nThe package provides the following URL endpoints:\n\n**User Notifications:**\n- `/api/notifications/user/` - Get all user notifications\n- `/api/notifications/user/categories/` - Get unread count by category\n- `/api/notifications/user/mark_all_as_read/` - Mark all user notifications as read\n- `/api/notifications/user/category/{category}/` - Get user notifications by category\n- `/api/notifications/user/category/{category}/mark_all_read` - Mark all user notifications in category as read\n- `/api/notifications/user/category/{category}/mark_read/{id}/` - Mark specific user notification as read\n\n**Broadcast Notifications:**\n- `/api/notifications/broadcast/` - Get all broadcast notifications\n- `/api/notifications/broadcast/category/{category}/` - Get broadcast notifications by category\n- `/api/notifications/broadcast/category/{category}/mark_read/{id}/` - Mark specific broadcast notification as read\n\n**WebSocket:**\n- `/api/notifications/ws_auth/` - WebSocket authentication endpoint (requires authentication, returns UUID)\n\n### 6. Run Migrations\n\n```bash\npython manage.py makemigrations\npython manage.py migrate\n```\n\n### 7. Register Custom Notification Models and Serializers\n\nThe package automatically discovers notification models and serializers. Ensure your custom notification models and serializers are properly imported in your Django app's `__init__.py` or `apps.py`:\n\n```python\n# In your app's apps.py\nfrom django.apps import AppConfig\n\nclass YourAppConfig(AppConfig):\n default_auto_field = 'django.db.models.BigAutoField'\n name = 'your_app'\n\n def ready(self):\n # Import your notification models and serializers to register them\n from .notifications import models, serializers\n```\n\nOr in your app's `__init__.py`:\n\n```python\n# In your app's __init__.py\ndefault_app_config = 'your_app.apps.YourAppConfig'\n```\n\n#### How Auto-Discovery Works\n\nThe package uses Django's app registry to automatically discover:\n\n1. **Notification Models**: All classes inheriting from `BaseNotificationModel`\n2. **Notification Serializers**: All classes inheriting from `BaseNotificationSerializer`\n\nThe discovery happens when Django starts up and loads all apps. Each model and serializer must have a `notification_class_name` attribute that matches between the model and its corresponding serializer.\n\n**Important**: Make sure your notification models and serializers are imported when Django starts, otherwise they won't be discovered by the package.\n\n## Usage\n\n### 1. Create Custom Notification Models\n\nCreate notification models by inheriting from `BaseNotificationModel`. You can define related models using either `PositiveIntegerField` (simple ID reference) or `ForeignKey` (full relationship). This example uses ForeignKey for better relationship management:\n\n```python\nfrom django.db import models\nfrom dj_notif.models import BaseNotificationModel\nfrom your_app.models import Task\n\nclass TaskNotification(BaseNotificationModel):\n class NotificationTitle(models.TextChoices):\n created = 'task_created'\n updated = 'task_updated'\n completed = 'task_completed'\n\n user = models.ForeignKey(User, related_name='task_notifications', on_delete=models.CASCADE)\n title = models.CharField(choices=NotificationTitle.choices, max_length=20)\n task = models.ForeignKey(Task, related_name='notifications', on_delete=models.SET_NULL)\n\n notification_class_name = 'task' # Required!\n```\n\n### 2. Create Custom Serializers\n\nCreate serializers by inheriting from `BaseNotificationSerializer`:\n\n```python\nfrom dj_notif.serializers import BaseNotificationSerializer\nfrom your_app.serializers import TaskSerializer\n\nclass TaskNotificationSerializer(BaseNotificationSerializer):\n notification_class_name = 'task' # Must match model\n task = TaskSerializer(fields=['id', 'name'])\n\n class Meta:\n model = TaskNotification\n extra_fields = ['user', 'task', 'requested_user']\n```\n\n#### Broadcast Notification Serializers\n\nFor broadcast notifications, inherit from `BaseBroadcastNotificationSerializer`:\n\n```python\nfrom dj_notif.serializers import BaseBroadcastNotificationSerializer\n\nclass BroadcastNotificationSerializer(BaseBroadcastNotificationSerializer):\n notification_class_name = 'broadcast' # Must match model\n\n class Meta:\n model = BroadcastNotification\n # No extra_fields needed for broadcast notifications\n```\n\n### 3. Using Notifications in Your Code\n\n#### Creating Notifications\n\n```python\n# Single notification\nTaskNotification.objects.create(\n user=user,\n title=TaskNotification.NotificationTitle.created,\n description=f'Task {task.name} has been created',\n level=1, # 1=low, 2=medium, 3=high\n task=task\n)\n\n# Multiple notifications at once\nTaskNotification.create_notifications(\n title='New Project Available',\n description='A new project has been created',\n level=2,\n users=[1, 2, 3, 4] # List of user IDs\n)\n\n# Broadcast notifications (sent to all users)\nBroadcastNotification.objects.create(\n title=BroadcastNotification.NotificationTitle.system_notification,\n description='System maintenance scheduled for tomorrow',\n level=2\n)\n```\n\n#### Using in Your Views or Services\n\n```python\n# In your views.py or services\ndef create_task_notification(user_id, task, action):\n \"\"\"Create a notification when a task is created, updated, or completed\"\"\"\n title_map = {\n 'created': TaskNotification.NotificationTitle.created,\n 'updated': TaskNotification.NotificationTitle.updated,\n 'completed': TaskNotification.NotificationTitle.completed,\n }\n \n TaskNotification.objects.create(\n user=user_id,\n title=title_map[action],\n description=f'Task {task.name} has been {action}',\n level=1,\n task=task\n )\n\n# Usage example\ncreate_task_notification(\n user_id=user,\n task=task,\n action='created'\n)\n```\n\n### 4. WebSocket Live Delivery\n\nNotifications are automatically delivered via WebSocket when they are created. To connect to the WebSocket, you need to follow a two-step authentication process:\n\n#### Step 1: Get WebSocket Authentication UUID\n\nFirst, make a GET request to the `ws_auth` endpoint to get a UUID:\n\n```javascript\n// Get WebSocket authentication UUID\nasync function getWsAuthUuid() {\n const response = await fetch('/api/notifications/ws_auth/', {\n method: 'GET',\n headers: {\n 'Authorization': 'Bearer your-jwt-token',\n 'Content-Type': 'application/json',\n },\n });\n \n if (response.ok) {\n const data = await response.json();\n return data.uuid; // UUID for WebSocket connection\n } else {\n throw new Error('Failed to get WebSocket auth UUID');\n }\n}\n```\n\n#### Step 2: Connect to WebSocket with UUID\n\nUse the UUID as a query parameter when connecting to the WebSocket:\n\n```javascript\n// Connect to WebSocket with authentication UUID\nasync function connectToWebSocket() {\n try {\n // Get authentication UUID\n const uuid = await getWsAuthUuid();\n \n // Connect to WebSocket with UUID\n const ws = new WebSocket(`ws://localhost:8000/ws/notifications/?uuid=${uuid}`);\n \n ws.onopen = function() {\n console.log('WebSocket connected successfully');\n };\n \n ws.onmessage = function(event) {\n const data = JSON.parse(event.data);\n console.log('New notification:', data);\n \n if (data.type === 'notifications') {\n // Handle notification data\n const notification = data.payload.notification;\n // Update UI, show toast, etc.\n }\n };\n \n ws.onerror = function(error) {\n console.error('WebSocket error:', error);\n };\n \n ws.onclose = function() {\n console.log('WebSocket connection closed');\n };\n \n return ws;\n } catch (error) {\n console.error('Failed to connect to WebSocket:', error);\n }\n}\n\n// Usage\nconst wsConnection = connectToWebSocket();\n```\n\n**Note**: WebSocket methods for getting notifications and marking them as read are not yet implemented. Use the REST API endpoints for these operations.\n\n#### Authentication Requirements\n\n- The `ws_auth` endpoint requires `IsAuthenticated` permission\n- You must include your JWT token in the Authorization header\n- The returned UUID is valid for a limited time\n- Use the UUID as a query parameter when connecting to the WebSocket\n\n## Supported Notification Types\n\nThe package supports various notification types. Here are examples using ForeignKey relationships:\n\n### Task Notifications\n```python\nfrom your_app.models import Task\n\nclass TaskNotification(BaseNotificationModel):\n class NotificationTitle(models.TextChoices):\n created = 'task_created'\n updated = 'task_updated'\n completed = 'task_completed'\n \n user = models.ForeignKey(User, related_name='task_notifications', on_delete=models.CASCADE)\n task = models.ForeignKey(Task, on_delete=models.SET_NULL)\n notification_class_name = 'task'\n```\n\n### Comment Notifications\n```python\nfrom your_app.models import Comment\n\nclass CommentNotification(BaseNotificationModel):\n class NotificationTitle(models.TextChoices):\n mention = 'mention'\n reply = 'reply'\n \n user = models.ForeignKey(User, related_name='comment_notifications', on_delete=models.CASCADE)\n comment = models.ForeignKey(Comment, on_delete=models.SET_NULL)\n notification_class_name = 'comment'\n```\n\n### Custom Notifications\n```python\nclass CustomNotification(BaseNotificationModel):\n class NotificationTitle(models.TextChoices):\n info = 'info'\n warning = 'warning'\n error = 'error'\n \n user = models.ForeignKey(User, related_name='custom_notifications', on_delete=models.CASCADE)\n custom_data = models.JSONField(default=dict) # Any additional data\n notification_class_name = 'custom'\n```\n\n### Broadcast Notifications\n```python\nclass BroadcastNotification(BaseBroadcastNotificationModel):\n class NotificationTitle(models.TextChoices):\n system_notification = 'system_notification'\n admin_notification = 'admin_notification'\n \n title = models.CharField(choices=NotificationTitle.choices, max_length=50)\n description = models.CharField(max_length=200)\n level = models.IntegerField(choices=[(1, 'Low'), (2, 'Medium'), (3, 'High')])\n # user_read_at_receipts field is automatically handled by BaseBroadcastNotificationModel\n notification_class_name = 'broadcast'\n```\n\n## API Endpoints\n\n### REST API\n\nThe package provides two types of notification endpoints:\n\n#### User Notifications\nUser-specific notifications that are sent to individual users. These notifications are tied to specific users and can be marked as read by the intended recipient.\n\n#### Broadcast Notifications \nSystem-wide notifications that are sent to all users. These notifications use a `user_read_at_receipts` JSON field to track which users have read them, allowing multiple users to mark the same notification as read.\n\n| Endpoint | Method | Description |\n|----------------------------------------------|--------|-------------|\n| `/api/notifications/user/` | GET | Get all user notifications for authenticated user |\n| `/api/notifications/user/categories/` | GET | Get unread count by category for user notifications |\n| `/api/notifications/user/mark_all_as_read/` | POST | Mark all user notifications as read |\n| `/api/notifications/user/category/{category}/` | GET | Get user notifications by category |\n| `/api/notifications/user/category/{category}/mark_all_read` | POST | Mark all user notifications in category as read |\n| `/api/notifications/user/category/{category}/mark_read/{id}/` | POST | Mark specific user notification as read |\n| `/api/notifications/broadcast/` | GET | Get all broadcast notifications for authenticated user |\n| `/api/notifications/broadcast/category/{category}/` | GET | Get broadcast notifications by category |\n| `/api/notifications/broadcast/category/{category}/mark_read/{id}/` | POST | Mark specific broadcast notification as read |\n| `/api/notifications/ws_auth/` | GET | WebSocket authentication endpoint |\n\n\n### WebSocket Live Delivery\n\nNotifications are automatically sent to connected clients when they are created. The WebSocket connection receives notifications in real-time without needing to send commands.\n\n**Note**: WebSocket commands for getting notifications and marking them as read are not yet implemented. Use the REST API for these operations.\n\n### API Usage Examples\n\n#### User Notifications\n```javascript\n// Get all user notifications\nconst response = await fetch('/api/notifications/user/', {\n headers: { 'Authorization': 'Bearer your-jwt-token' }\n});\n\n// Get unread count by category\nconst categories = await fetch('/api/notifications/user/categories/', {\n headers: { 'Authorization': 'Bearer your-jwt-token' }\n});\n\n// Mark specific notification as read\nawait fetch('/api/notifications/user/category/task/mark_read/123/', {\n method: 'POST',\n headers: { 'Authorization': 'Bearer your-jwt-token' }\n});\n```\n\n#### Broadcast Notifications\n```javascript\n// Get all broadcast notifications\nconst response = await fetch('/api/notifications/broadcast/', {\n headers: { 'Authorization': 'Bearer your-jwt-token' }\n});\n\n// Get broadcast notifications by category\nconst systemNotifs = await fetch('/api/notifications/broadcast/category/pm_broadcast/', {\n headers: { 'Authorization': 'Bearer your-jwt-token' }\n});\n\n// Mark broadcast notification as read (for current user)\nawait fetch('/api/notifications/broadcast/category/pm_broadcast/mark_read/456/', {\n method: 'POST',\n headers: { 'Authorization': 'Bearer your-jwt-token' }\n});\n```\n\n## Configuration Options\n\n### Notification Levels\n\n```python\nclass NotificationLevel(models.IntegerChoices):\n low = 1\n medium = 2\n high = 3\n```\n\n### Channel Name Format\n\nNotifications are sent to channels in the format: `notif_user_{user_id}`\n\n## Dependencies\n\n- Django >= 5.2\n- Django REST Framework >= 3.15.2\n- Django Channels >= 4.2.0\n- django-channels-jwt >= 0.0.3\n- Redis (for channel layers)\n\n## Example Project Structure\n\n```\nyour_project/\n\u251c\u2500\u2500 apps/\n\u2502 \u2514\u2500\u2500 your_app/\n\u2502 \u251c\u2500\u2500 notifications/\n\u2502 \u2502 \u251c\u2500\u2500 __init__.py\n\u2502 \u2502 \u251c\u2500\u2500 models.py # Custom notification models\n\u2502 \u2502 \u2514\u2500\u2500 serializers.py # Custom notification serializers\n\u2502 \u251c\u2500\u2500 models.py # Your main models\n\u2502 \u251c\u2500\u2500 signals.py # Django signals for notifications\n\u2502 \u251c\u2500\u2500 apps.py # App configuration\n\u2502 \u2514\u2500\u2500 __init__.py\n\u251c\u2500\u2500 your_project/\n\u2502 \u251c\u2500\u2500 asgi.py # ASGI configuration with WebSocket routing\n\u2502 \u251c\u2500\u2500 settings.py # Django settings with channels config\n\u2502 \u2514\u2500\u2500 urls.py # URL configuration\n\u2514\u2500\u2500 manage.py\n```\n\n### Recommended File Organization\n\n1. **Create a `notifications/` subdirectory** in each app that needs notifications\n2. **Place notification models** in `notifications/models.py`\n3. **Place notification serializers** in `notifications/serializers.py`\n4. **Import notifications** in your app's `apps.py` or `__init__.py`\n5. **Use signals** in your main app's `signals.py` to trigger notifications\n\n### Example App Structure\n\n```python\n# apps/your_app/notifications/__init__.py\n# This file can be empty, but ensures the directory is a Python package\n\n# apps/your_app/notifications/models.py\nfrom dj_notif.models import BaseNotificationModel\n\nclass YourNotification(BaseNotificationModel):\n # Your notification model definition\n pass\n\n# apps/your_app/notifications/serializers.py\nfrom dj_notif.serializers import BaseNotificationSerializer\n\nclass YourNotificationSerializer(BaseNotificationSerializer):\n # Your notification serializer definition\n pass\n\n# apps/your_app/apps.py\nfrom django.apps import AppConfig\n\nclass YourAppConfig(AppConfig):\n default_auto_field = 'django.db.models.BigAutoField'\n name = 'your_app'\n\n def ready(self):\n # Import to register notifications\n from .notifications import models, serializers\n from . import signals # Import signals to register them\n```\n\n## Best Practices\n\n### 1. Notification Naming Conventions\n\n- Use descriptive names for notification classes: `TaskAssignmentNotification`, `CommentMentionNotification`\n- Use consistent naming for `notification_class_name`: lowercase with underscores\n- Group related notifications in the same model with different titles\n\n### 2. Signal Organization\n\n- Keep signal handlers focused and lightweight\n- Use transaction management for critical operations\n- Handle exceptions gracefully to prevent signal failures\n- Consider using `@receiver` decorators with `dispatch_uid` for unique signal handlers\n\n### 3. Performance Considerations\n\n- Use `bulk_create()` for multiple notifications when possible\n- Consider using `select_related()` and `prefetch_related()` in serializers\n- Implement pagination for notification lists\n- Use database indexes on frequently queried fields\n\n### 4. Security Best Practices\n\n- Always validate user permissions before creating notifications\n- Use proper authentication for WebSocket connections\n- Sanitize notification content to prevent XSS attacks\n- Implement rate limiting for notification creation\n\n### 5. Testing Notifications\n\n```python\nfrom django.test import TestCase\nfrom your_app.notifications.models import TaskNotification\n\nclass NotificationTestCase(TestCase):\n def setUp(self):\n self.user_id = 1 # Simple user ID\n \n def test_notification_creation(self):\n notification = TaskNotification.objects.create(\n user=self.user_id,\n title='task_created',\n description='Test notification',\n level=1,\n task_id=123\n )\n self.assertEqual(notification.user, self.user_id)\n self.assertEqual(notification.title, 'task_created')\n self.assertEqual(notification.task_id, 123)\n \n def test_notification_dispatch(self):\n # Test that notifications are dispatched when saved\n with self.assertNumQueries(1): # Adjust based on your setup\n notification = TaskNotification.objects.create(\n user=self.user_id,\n title='task_created',\n description='Test notification',\n level=1,\n task_id=123\n )\n```\n\n## Troubleshooting\n\n### Common Issues\n\n1. **WebSocket Connection Fails**\n - Ensure Redis is running\n - Check JWT token validity\n - Verify ASGI configuration\n\n2. **Notifications Not Sending**\n - Check channel layer configuration\n - Ensure `notification_class_name` is set in models\n - Verify serializer registration\n\n3. **Migration Errors**\n - Run `python manage.py makemigrations dj_notif`\n - Ensure all custom notification models are in `INSTALLED_APPS`\n\n### Debug Mode\n\nEnable debug logging in settings:\n\n```python\nLOGGING = {\n 'version': 1,\n 'disable_existing_loggers': False,\n 'handlers': {\n 'console': {\n 'class': 'logging.StreamHandler',\n },\n },\n 'loggers': {\n 'notification': {\n 'handlers': ['console'],\n 'level': 'DEBUG',\n },\n },\n}\n```\n\n## Deployment\n\n### Production Considerations\n\n1. **Redis Configuration**\n ```python\n CHANNEL_LAYERS = {\n 'default': {\n 'BACKEND': 'channels_redis.core.RedisChannelLayer',\n 'CONFIG': {\n \"hosts\": [('your-redis-host', 6379)],\n \"capacity\": 1500, # Maximum number of messages in a channel\n \"expiry\": 10, # Message expiry in seconds\n },\n },\n }\n ```\n\n2. **ASGI Server**\n - Use Daphne or Uvicorn for production\n - Configure proper worker processes\n - Set up load balancing for WebSocket connections\n\n3. **Security**\n - Use HTTPS/WSS in production\n - Configure proper CORS settings\n - Implement rate limiting\n - Use secure JWT secrets\n\n4. **Monitoring**\n - Monitor Redis memory usage\n - Track WebSocket connection counts\n - Set up alerts for notification failures\n - Log notification delivery rates\n\n### Docker Deployment\n\n```dockerfile\n# Example Dockerfile\nFROM python:3.11\n\nWORKDIR /app\nCOPY requirements.txt .\nRUN pip install -r requirements.txt\n\nCOPY . .\n\nEXPOSE 8000\n\n# Option 1: Using Daphne (ASGI server for WebSocket support)\nCMD [\"daphne\", \"-b\", \"0.0.0.0\", \"-p\", \"8000\", \"your_project.asgi:application\"]\n\n# Option 2: Using Gunicorn with Uvicorn (ASGI server for WebSocket support)\nCMD [\"gunicorn\", \"--bind\", \"0.0.0.0:8000\", \"--worker-class\", \"uvicorn.workers.UvicornWorker\", \"your_project.asgi:application\"]\n```\n\n### Environment Variables\n\n```bash\n# Required environment variables\nREDIS_URL=redis://your-redis-host:6379\nCHANNEL_LAYERS_JWT_SECRET=your-secret-key\nDJANGO_SECRET_KEY=your-django-secret\n\n# Optional\nREDIS_CAPACITY=1500\nREDIS_EXPIRY=10\n```\n\n## Migration and Upgrades\n\n### Upgrading from Previous Versions\n\nWhen upgrading the package, follow these steps:\n\n1. **Backup your database** before running migrations\n2. **Update the package**: `pip install --upgrade dj_notif`\n3. **Run migrations**: `python manage.py migrate`\n4. **Test your notification system** thoroughly\n5. **Update your code** if any breaking changes are introduced\n\n### Breaking Changes\n\nCheck the [CHANGELOG.md](CHANGELOG.md) file for detailed information about breaking changes between versions.\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests\n5. Submit a pull request\n\n### Development Setup\n\n```bash\n# Clone the repository\ngit clone https://github.com/your-username/dj_notif.git\ncd dj_notif\n\n# Create virtual environment\npython -m venv venv\nsource venv/bin/activate # On Windows: venv\\Scripts\\activate\n\n# Install development dependencies\npip install -e .\npip install -r requirements-dev.txt\n\n# Run tests\npython manage.py test dj_notif\n```\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.\n\n## Support\n\nFor support and questions, please open an issue on the GitHub repository or contact the maintainer.\n\n## Changelog\n\n### Version 0.2.0 (Latest)\n- \u2728 **Broadcast Notifications**: Added support for system-wide notifications sent to all users\n- \ud83d\udd04 **Separate ViewSets**: Split user notifications and broadcast notifications into separate ViewSets\n- \ud83d\udcca **Enhanced API Structure**: Reorganized API endpoints with `/user/` and `/broadcast/` prefixes\n- \ud83c\udfaf **Multi-user Read Tracking**: Broadcast notifications use `user_read_at_receipts` JSON field for read status\n- \ud83d\udd27 **Improved URL Routing**: Better organized URL structure for different notification types\n- \ud83d\udcdd **BaseBroadcastNotificationModel**: New base model for broadcast notifications\n- \ud83d\udcdd **BaseBroadcastNotificationSerializer**: New base serializer for broadcast notifications\n- \ud83d\ude80 **Auto-discovery Support**: Broadcast notifications work with the existing auto-discovery system\n\n### Version 0.1.0\n- \ud83c\udf89 **Initial release**\n- \ud83d\udd14 **WebSocket-based real-time notifications**: Live notification delivery via WebSocket connections\n- \ud83d\udcca **REST API for notification management**: Complete CRUD operations for notifications\n- \ud83d\udd10 **JWT authentication support**: Secure authentication for both REST API and WebSocket connections\n- \u26a1 **Automatic notification dispatching**: Notifications are automatically sent when models are saved\n- \ud83d\udcf1 **Category-based notification organization**: Group notifications by type (task assignments, comments, etc.)\n- \ud83d\udd04 **Soft delete functionality**: Built-in soft delete for data integrity\n- \ud83c\udfa8 **Customizable notification types**: Easy to extend with custom notification models and serializers\n- \ud83d\udd0d **Auto-discovery system**: Automatic discovery of notification models and serializers\n- \ud83d\udcc8 **Read/unread tracking**: Mark notifications as read individually or by category\n- \ud83c\udf10 **WebSocket authentication**: Secure WebSocket connections with JWT token validation\n",
"bugtrack_url": null,
"license": "MIT License\n \n Copyright (c) 2025 Armin Fekri\n \n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n \n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n \n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.\n ",
"summary": "A comprehensive Django package for managing notifications with automatic dispatching, WebSocket-based real-time delivery, and category-based organization",
"version": "0.2.2",
"project_urls": {
"Changelog": "https://github.com/Hexoder/DjangoNotification/blob/main/CHANGELOG.md",
"Documentation": "https://github.com/Hexoder/DjangoNotification#readme",
"Homepage": "https://github.com/Hexoder/DjangoNotification",
"Issues": "https://github.com/Hexoder/DjangoNotification/issues",
"Repository": "https://github.com/Hexoder/DjangoNotification"
},
"split_keywords": [
"django",
" notifications",
" websocket",
" real-time",
" channels",
" jwt",
" broadcast",
" rest-api"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "cc06467845b71399bc5fedac3f46eb084387d958d4b9e175a4cd4dbc6d88bfc0",
"md5": "659c7c0a6faa54515b71791437faae5c",
"sha256": "48879eae587c49184eb653eaab7b4e6dda0681533d0ba138ca0691f34ec93de6"
},
"downloads": -1,
"filename": "dj_notif-0.2.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "659c7c0a6faa54515b71791437faae5c",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 21456,
"upload_time": "2025-08-02T15:40:52",
"upload_time_iso_8601": "2025-08-02T15:40:52.318993Z",
"url": "https://files.pythonhosted.org/packages/cc/06/467845b71399bc5fedac3f46eb084387d958d4b9e175a4cd4dbc6d88bfc0/dj_notif-0.2.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "c9e177415df6f3f5c67d92d04aa3604fd2014d8fcc43b4cb628e4dbe19196ec6",
"md5": "90c4cbe9ab5d63a183581cd20e96862b",
"sha256": "313d3178806f1f8919948251f094a563c37b3e72f06fc1b9fcd10de369a2ba01"
},
"downloads": -1,
"filename": "dj_notif-0.2.2.tar.gz",
"has_sig": false,
"md5_digest": "90c4cbe9ab5d63a183581cd20e96862b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 27065,
"upload_time": "2025-08-02T15:40:53",
"upload_time_iso_8601": "2025-08-02T15:40:53.474244Z",
"url": "https://files.pythonhosted.org/packages/c9/e1/77415df6f3f5c67d92d04aa3604fd2014d8fcc43b4cb628e4dbe19196ec6/dj_notif-0.2.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-02 15:40:53",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Hexoder",
"github_project": "DjangoNotification",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "dj-notif"
}