CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-django-notifications-hq

GitHub notifications alike app for Django providing comprehensive activity tracking and notification features.

Pending
Overview
Eval results
Files

configuration.mddocs/

Configuration

Configurable settings for pagination, soft deletion, JSON field usage, caching, and other behavioral options with sensible defaults and Django settings integration.

Capabilities

Settings Function

Function to retrieve merged configuration combining defaults with user-specified settings.

def get_config():
    """
    Get merged configuration with user settings and defaults.
    
    Returns:
        dict: Configuration dictionary with all settings
        
    Configuration Keys:
        PAGINATE_BY (int): Number of notifications per page (default: 20)
        USE_JSONFIELD (bool): Enable JSONField for extra data (default: False)  
        SOFT_DELETE (bool): Use soft deletion instead of hard delete (default: False)
        NUM_TO_FETCH (int): Default number for API endpoints (default: 10)
        CACHE_TIMEOUT (int): Cache timeout in seconds (default: 2)
        
    Django Setting:
        DJANGO_NOTIFICATIONS_CONFIG (dict): User configuration overrides
    """

Default Configuration

CONFIG_DEFAULTS = {
    'PAGINATE_BY': 20,
    'USE_JSONFIELD': False,
    'SOFT_DELETE': False,
    'NUM_TO_FETCH': 10,
    'CACHE_TIMEOUT': 2,
}

Usage Examples

Basic Configuration Setup

# In your Django settings.py
DJANGO_NOTIFICATIONS_CONFIG = {
    'PAGINATE_BY': 25,           # Show 25 notifications per page
    'USE_JSONFIELD': True,       # Enable extra data storage
    'SOFT_DELETE': True,         # Use soft deletion
    'NUM_TO_FETCH': 15,          # Fetch 15 notifications by default in API
    'CACHE_TIMEOUT': 30,         # Cache notification counts for 30 seconds
}

# The configuration is automatically loaded by the package
from notifications.settings import get_config

config = get_config()
print(config['PAGINATE_BY'])  # Output: 25
print(config['SOFT_DELETE'])  # Output: True

Production Configuration

# settings/production.py
DJANGO_NOTIFICATIONS_CONFIG = {
    # Higher pagination for performance
    'PAGINATE_BY': 50,
    
    # Enable JSON field for rich notification data
    'USE_JSONFIELD': True,
    
    # Use soft delete to maintain data integrity
    'SOFT_DELETE': True,
    
    # Fetch more notifications for mobile apps
    'NUM_TO_FETCH': 25,
    
    # Longer cache timeout for better performance
    'CACHE_TIMEOUT': 300,  # 5 minutes
}

Development Configuration

# settings/development.py
DJANGO_NOTIFICATIONS_CONFIG = {
    # Smaller pagination for easier testing
    'PAGINATE_BY': 5,
    
    # Enable JSON field for testing data structures
    'USE_JSONFIELD': True,
    
    # Disable soft delete for easier debugging
    'SOFT_DELETE': False,
    
    # Fetch fewer notifications for faster development
    'NUM_TO_FETCH': 5,
    
    # Short cache timeout for immediate feedback
    'CACHE_TIMEOUT': 1,
}

Configuration-Aware Code

from notifications.settings import get_config

def create_notification_page(request):
    """Create paginated notification view using configuration."""
    config = get_config()
    
    notifications = request.user.notifications.all()
    
    # Use configured pagination
    paginator = Paginator(notifications, config['PAGINATE_BY'])
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    return render(request, 'notifications/list.html', {
        'notifications': page_obj,
        'config': config
    })

def send_rich_notification(sender, recipient, verb, **extra_data):
    """Send notification with optional JSON data based on configuration."""
    config = get_config()
    
    notification_kwargs = {
        'sender': sender,
        'recipient': recipient,
        'verb': verb
    }
    
    # Only include extra data if JSON field is enabled
    if config['USE_JSONFIELD'] and extra_data:
        notification_kwargs.update(extra_data)
    
    notify.send(**notification_kwargs)

def get_cached_notification_count(user):
    """Get notification count with configured cache timeout."""
    config = get_config()
    
    cache_key = f'notification_count_{user.id}'
    count = cache.get(cache_key)
    
    if count is None:
        count = user.notifications.unread().count()
        cache.set(cache_key, count, config['CACHE_TIMEOUT'])
    
    return count

Conditional Features Based on Configuration

from notifications.settings import get_config

class NotificationManager:
    def __init__(self):
        self.config = get_config()
    
    def delete_notification(self, notification):
        """Delete notification using configured deletion method."""
        if self.config['SOFT_DELETE']:
            notification.deleted = True
            notification.save()
        else:
            notification.delete()
    
    def get_active_notifications(self, user):
        """Get notifications respecting soft delete configuration."""
        notifications = user.notifications.all()
        
        if self.config['SOFT_DELETE']:
            notifications = notifications.filter(deleted=False)
        
        return notifications
    
    def prepare_notification_data(self, notification, extra_data=None):
        """Prepare notification data based on configuration."""
        data = {
            'actor': str(notification.actor),
            'verb': notification.verb,
            'timestamp': notification.timestamp.isoformat(),
        }
        
        # Include JSON data if enabled
        if self.config['USE_JSONFIELD'] and notification.data:
            data['extra_data'] = notification.data
        
        # Include additional data if provided and JSON field enabled  
        if self.config['USE_JSONFIELD'] and extra_data:
            data.update(extra_data)
            
        return data

# Usage
manager = NotificationManager()
user_notifications = manager.get_active_notifications(user)

API Configuration

from notifications.settings import get_config
from django.http import JsonResponse

def notification_api_endpoint(request):
    """API endpoint that respects configuration settings."""
    config = get_config()
    
    # Use configured default fetch count
    max_count = request.GET.get('max', config['NUM_TO_FETCH'])
    try:
        max_count = min(int(max_count), 100)  # Cap at 100
    except (ValueError, TypeError):
        max_count = config['NUM_TO_FETCH']
    
    notifications = request.user.notifications.unread()[:max_count]
    
    notification_list = []
    for notification in notifications:
        notif_data = {
            'id': notification.id,
            'actor': str(notification.actor),
            'verb': notification.verb,
            'timestamp': notification.timestamp.isoformat(),
        }
        
        # Include JSON data if configured
        if config['USE_JSONFIELD'] and notification.data:
            notif_data['data'] = notification.data
            
        notification_list.append(notif_data)
    
    return JsonResponse({
        'notifications': notification_list,
        'count': len(notification_list),
        'config': {
            'max_per_request': config['NUM_TO_FETCH'],
            'pagination_size': config['PAGINATE_BY'],
            'cache_timeout': config['CACHE_TIMEOUT']
        }
    })

Template Configuration Context

from notifications.settings import get_config

def add_config_to_context(request):
    """Context processor to add configuration to templates."""
    return {
        'notifications_config': get_config()
    }

# In settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'OPTIONS': {
            'context_processors': [
                # ... other context processors
                'myapp.context_processors.add_config_to_context',
            ],
        },
    },
]
<!-- In templates -->
{% load notifications_tags %}

<!-- Use configuration in templates -->
<div class="notifications-config">
    <p>Showing {{ notifications_config.PAGINATE_BY }} notifications per page</p>
    
    {% if notifications_config.SOFT_DELETE %}
        <p>Deleted notifications are preserved</p>
    {% endif %}
    
    {% if notifications_config.USE_JSONFIELD %}
        <!-- Show rich notification data -->
        {% for notification in notifications %}
            {% if notification.data %}
                <div class="notification-extra-data">
                    {{ notification.data|safe }}
                </div>
            {% endif %}
        {% endfor %}
    {% endif %}
</div>

<!-- Configure template tag with settings -->
{% register_notify_callbacks 
    fetch=notifications_config.NUM_TO_FETCH
    refresh_period=notifications_config.CACHE_TIMEOUT
%}

Migration and Configuration Changes

# Custom management command to handle configuration changes
from django.core.management.base import BaseCommand
from notifications.settings import get_config
from notifications.models import Notification

class Command(BaseCommand):
    help = 'Migrate notifications based on configuration changes'
    
    def handle(self, *args, **options):
        config = get_config()
        
        if config['SOFT_DELETE']:
            # Ensure deleted field exists and is properly indexed
            self.stdout.write("Soft delete is enabled")
            
            # Count notifications that would be affected
            hard_deleted_count = Notification.objects.filter(deleted=True).count()
            self.stdout.write(f"Found {hard_deleted_count} soft-deleted notifications")
            
        else:
            # Warn about data that might be lost
            soft_deleted_count = Notification.objects.filter(deleted=True).count()
            if soft_deleted_count > 0:
                self.stdout.write(
                    self.style.WARNING(
                        f"Warning: {soft_deleted_count} soft-deleted notifications exist "
                        "but SOFT_DELETE is False. These may not be visible."
                    )
                )
        
        if config['USE_JSONFIELD']:
            # Check for notifications with JSON data
            with_data_count = Notification.objects.exclude(data__isnull=True).count()
            self.stdout.write(f"Found {with_data_count} notifications with JSON data")
        
        self.stdout.write(
            self.style.SUCCESS(f"Configuration check complete. Current settings: {config}")
        )

Environment-Specific Configuration

# settings/base.py
import os

# Base notification configuration
DJANGO_NOTIFICATIONS_CONFIG = {
    'PAGINATE_BY': int(os.environ.get('NOTIFICATIONS_PAGINATE_BY', '20')),
    'USE_JSONFIELD': os.environ.get('NOTIFICATIONS_USE_JSONFIELD', 'False').lower() == 'true',  
    'SOFT_DELETE': os.environ.get('NOTIFICATIONS_SOFT_DELETE', 'False').lower() == 'true',
    'NUM_TO_FETCH': int(os.environ.get('NOTIFICATIONS_NUM_TO_FETCH', '10')),
    'CACHE_TIMEOUT': int(os.environ.get('NOTIFICATIONS_CACHE_TIMEOUT', '2')),
}

# Environment variables:
# NOTIFICATIONS_PAGINATE_BY=25
# NOTIFICATIONS_USE_JSONFIELD=true  
# NOTIFICATIONS_SOFT_DELETE=true
# NOTIFICATIONS_NUM_TO_FETCH=15
# NOTIFICATIONS_CACHE_TIMEOUT=30

Install with Tessl CLI

npx tessl i tessl/pypi-django-notifications-hq

docs

admin-integration.md

api-endpoints.md

configuration.md

core-system.md

index.md

signals.md

template-integration.md

utilities.md

web-interface.md

tile.json