Installation

Requirements

  • Django 3.2+

  • Django Channels 3.0+

  • Redis server

  • Python 3.8+

Installing the Package

You can install Django Admin Collaborator via pip:

pip install django-admin-collaborator

Configuration

1. Add Required Applications

Add to INSTALLED_APPS in your Django settings:

INSTALLED_APPS = [
    ...
    'channels',
    'django_admin_collaborator',
    ...
]

2. Configure Django Settings

Add the following to your project’s settings.py:

# Required: Configure Redis connection
ADMIN_COLLABORATOR_REDIS_URL = 'redis://localhost:6379/0'

# Required: Configure Channels to use Redis as the backend
CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            'hosts': [('127.0.0.1', 6379)],
        },
    },
}

# Optional: Configure custom admin URL
ADMIN_COLLABORATOR_ADMIN_URL = 'admin'  # default: 'admin'

# Optional: Configure WebSocket connection URL prefix
ADMIN_COLLABORATOR_WEBSOCKET_CONNECTION_PREFIX_URL = 'admin/collaboration'

# Optional: Redis connection resilience settings
ADMIN_COLLABORATOR_REDIS_MAX_RETRIES = 3  # Maximum retry attempts for Redis operations
ADMIN_COLLABORATOR_REDIS_RETRY_DELAY = 0.5  # Delay between retries (seconds, uses exponential backoff)
ADMIN_COLLABORATOR_REDIS_SOCKET_TIMEOUT = 5  # Redis connection timeout (seconds)
ADMIN_COLLABORATOR_REDIS_MAX_CONNECTIONS = 10  # Maximum connections in the Redis pool

# Optional: Customize notification messages and avatar settings
ADMIN_COLLABORATOR_OPTIONS = {
    "editor_mode_text": "You are in editor mode.",
    "viewer_mode_text": "This page is being edited by {editor_name}. You cannot make changes until they leave.",
    "claiming_editor_text": "The editor has left. The page will refresh shortly to allow editing.",
    "avatar_field": None,  # Name of the field containing the user's avatar image
    "notification_request_interval": 15,  # Seconds between notification requests
    "notification_message": "User {username} is requesting the editors attention.",
    "notification_button_text": "Request Editor Attention",
    "notification_request_sent_text": "Request sent.",  # Message shown to the requester
    # Chat settings
    "enable_chat": True,  # Enable/disable the chat feature
    "chat_user_list_title": "Online Users",  # Title for the user list panel
    "chat_empty_state_text": "No other users online",  # Text when no users are online
    "chat_start_conversation_text": "No messages yet. Start the conversation!",  # Text for empty chat
}

3. Set Up ASGI Application

Create or modify your asgi.py file:

from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack

# first get asgi application
django_asgi_app = get_asgi_application()

# then import websocket_urlpatterns
from django_admin_collaborator.routing import websocket_urlpatterns

application = ProtocolTypeRouter({
    'http': django_asgi_app,
    'websocket': AuthMiddlewareStack(
        URLRouter(
            websocket_urlpatterns
        )
    ),
})

4. Run with ASGI Server

Start your project using an ASGI server:

# Using Daphne
daphne yourproject.asgi:application

# OR using Uvicorn
uvicorn yourproject.asgi:application --host 0.0.0.0 --reload --reload-include '*.html'

Deployment

Database connection handling

As of v0.4.5, the WebSocket consumer force-closes its DB connection after each authorization check, so the package is safe to use with any CONN_MAX_AGE setting — including persistent connections (CONN_MAX_AGE > 0). No special configuration is required.

Earlier versions (≤ v0.4.4): the consumer relied on Channels’ default close_old_connections() cleanup, which only closes connections older than CONN_MAX_AGE. Because the sync_to_async thread pool keeps worker threads alive indefinitely, every concurrent WebSocket connect could hold a Postgres connection until that thread was reused. Under heavy refresh / many concurrent admin users this exhausted max_connections. The historical workaround was to disable persistent connections:

# settings.py — only required on django-admin-collaborator <= 0.4.4
if not DEBUG:
    import django_heroku
    django_heroku.settings(locals())
    DATABASES['default']['CONN_MAX_AGE'] = 0

Upgrade to 0.4.5+ to remove this constraint and enable persistent connections elsewhere in your project.

Redis Connection Resilience

For production deployments, especially on platforms like Heroku, you may experience occasional “Connection reset by peer” errors with Redis. The package includes built-in resilience features that can be configured:

# Increase retry attempts for unstable connections
ADMIN_COLLABORATOR_REDIS_MAX_RETRIES = 5

# Adjust backoff delay between retries
ADMIN_COLLABORATOR_REDIS_RETRY_DELAY = 0.5  # seconds

# Increase socket timeout for slow network conditions
ADMIN_COLLABORATOR_REDIS_SOCKET_TIMEOUT = 10  # seconds

# Adjust connection pool size based on your application's traffic
ADMIN_COLLABORATOR_REDIS_MAX_CONNECTIONS = 20