API Reference

This section provides detailed documentation for the Django Admin Collaborator API.

Admin Mixins

class django_admin_collaborator.utils.CollaborativeAdminMixin[source]

Bases: object

Mixin for ModelAdmin classes to enable collaborative editing.

Adds the JS/CSS assets for the collaboration UI and injects a window-scoped config object so the JS can read user-customizable strings.

Adds collaborative editing capabilities to a Django ModelAdmin. Provides real-time editing locks, user presence, and the chat UI.

class Media[source]

Bases: object

css = {'all': ['django_admin_collaborator/css/admin_chat.css']}
js = ['django_admin_collaborator/js/admin_edit.js', 'django_admin_collaborator/js/admin_chat.js']
change_view(request, object_id, form_url='', extra_context=None)[source]

WebSocket Consumers

class django_admin_collaborator.consumers.AdminCollaborationConsumer(*args, **kwargs)[source]

Bases: RedisClientMixin, AsyncWebsocketConsumer

WebSocket consumer for real-time collaborative editing in Django admin.

This consumer manages edit locks for admin model instances, ensuring only one staff user can edit a specific object at a time. It also broadcasts editing status and updates to all connected clients.

Communication is coordinated through Redis for lock management and message distribution via Django Channels layer for WebSocket messaging. Redis client, connection pool, auth check, and timestamp helpers live on RedisClientMixin.

Handles WebSocket connections for the collaborative edit lock and editor-presence features on an admin detail page.

async attention_requested(event: Dict[str, Any]) None[source]

Handle attention_requested events from the channel layer.

Parameters:

event (Dict[str, Any]) – Event data including user_id, username, and timestamp

async connect() None[source]

Handle WebSocket connection establishment.

  • Extracts model and object identifiers from URL

  • Authenticates the user

  • Sets up channel group for this specific object

  • Notifies other users about this user’s presence

  • Retrieves and maintains last modified timestamp

Closes the connection if user is not authorized.

async content_updated(event: Dict[str, Any]) None[source]

Handle content_updated events from the channel layer.

Parameters:

event (Dict[str, Any]) – Event data including user_id, username, and timestamp

async disconnect(close_code: int) None[source]

Handle WebSocket disconnection.

  • Removes user from the editor role if they were the active editor

  • Notifies other users about this user leaving

  • Leaves the channel group

  • Stores editor ID as previous editor to allow reclaiming on reconnection

Parameters:

close_code (int) – WebSocket close code

async editor_status(event: Dict[str, Any]) None[source]

Handle editor_status events from the channel layer.

Parameters:

event (Dict[str, Any]) – Event data including editor_id and editor_name

get_last_modified() str[source]

Retrieve the last modified timestamp for the current object.

This is a placeholder that should be implemented based on your actual model. Default implementation returns current timestamp.

Returns:

Last modified timestamp in ISO format

Return type:

str

async handle_claim_editor(timestamp: Optional[str]) None[source]

Process a request to claim editor status for the current object.

Only assigns editor status if no other user currently has it. Sets a 3-minute expiration on the editor lock to handle disconnections. Gives priority to the previous editor during reconnection for a short grace period.

Parameters:

timestamp (Optional[str]) – Optional timestamp string in ISO format

async handle_content_updated(timestamp: Optional[str]) None[source]

Process content update notifications.

Updates the last modified timestamp and notifies all connected clients that content has changed.

Parameters:

timestamp (Optional[str]) – Optional timestamp string in ISO format

async handle_editor_status_request() None[source]

Handle requests for the current editor status.

Checks Redis for current editor information and sends it to the requester. If the current editor hasn’t sent a heartbeat recently, clears the editor lock.

async handle_heartbeat() None[source]

Process heartbeat messages from the active editor.

Updates the last heartbeat timestamp and resets the expiration time for the editor lock in Redis. Only processes heartbeats from the current editor.

Also stores the current editor ID as the previous editor with a longer expiration time to handle temporary disconnections.

async handle_release_lock() None[source]

Process a request to release the editor lock.

Only allows the current editor to release their own lock. Updates the last modified timestamp and notifies all clients that the lock has been released.

async handle_request_attention() None[source]

Process a request for the editor’s attention from a viewer.

Checks if the user can send a notification based on rate limiting, then forwards the request to the current editor.

async lock_released(event: Dict[str, Any]) None[source]

Handle lock_released events from the channel layer.

Parameters:

event (Dict[str, Any]) – Event data including user_id, username, and timestamp

async receive(text_data: str) None[source]

Process incoming WebSocket messages.

Routes each message to the appropriate handler based on its type.

Parameters:

text_data (str) – JSON string containing the message data

async user_joined(event: Dict[str, Any]) None[source]

Handle user_joined events from the channel layer.

Parameters:

event (Dict[str, Any]) – Event data including user_id, username, and timestamp

async user_left(event: Dict[str, Any]) None[source]

Handle user_left events from the channel layer.

Parameters:

event (Dict[str, Any]) – Event data including user_id and username

class django_admin_collaborator.consumers.ChatConsumer(*args, **kwargs)[source]

Bases: RedisClientMixin, AsyncWebsocketConsumer

WebSocket consumer for real-time chat between users on the same page.

Manages presence tracking and message routing between users viewing the same page in the Django admin. Redis client, connection pool, auth check, and timestamp helpers live on RedisClientMixin.

Handles WebSocket connections for the per-page chat panel between admin users viewing the same object.

async chat_message(event: Dict[str, Any]) None[source]

Handle chat_message events and relay to the WebSocket.

Parameters:

event (Dict[str, Any]) – Event data containing message information

async connect() None[source]

Handle WebSocket connection establishment.

  • Extracts current page path from URL

  • Authenticates the user

  • Sets up channel group for users on this page

  • Adds user to the presence list

  • Notifies other users about this user’s presence

async disconnect(close_code: int) None[source]

Handle WebSocket disconnection.

  • Removes user from active users list

  • Notifies other users about this user leaving

  • Leaves the channel group

async handle_chat_message(recipient_id: int, message: str) None[source]

Process and route chat messages between users.

Parameters:
  • recipient_id (int) – ID of the user receiving the message

  • message (str) – Content of the chat message

async handle_heartbeat() None[source]

Process heartbeat messages to keep track of active users.

Updates the user’s last_seen timestamp in Redis

async receive(text_data: str) None[source]

Process incoming WebSocket messages.

Routes each message to the appropriate handler based on its type.

Parameters:

text_data (str) – JSON string containing the message data

async user_joined(event: Dict[str, Any]) None[source]

Handle user_joined events and relay to the WebSocket.

Parameters:

event (Dict[str, Any]) – Event data containing user information

async user_left(event: Dict[str, Any]) None[source]

Handle user_left events and relay to the WebSocket.

Parameters:

event (Dict[str, Any]) – Event data containing user information

Module-level helpers

django_admin_collaborator.consumers.get_utc_timestamp() str[source]

Return the current time as a UTC ISO-8601 string with timezone info.

class django_admin_collaborator.consumers.RedisClientMixin(*args, **kwargs)[source]

Bases: object

Shared Redis client + pool + retry-wrapped helpers for the WebSocket consumers.

Both consumer classes used to duplicate this block verbatim. A single pool on the mixin means both classes share Redis connections (lower client count against managed Redis plans like Heroku Redis).

Shared Redis client, connection pool, retry-wrapped helpers, and authentication helper. Both bundled consumers inherit from this; you can also inherit from it if you build your own consumer.

async check_user_authorization() bool[source]

Validate the connection’s user is authenticated + has staff permissions.

get_timestamp() str[source]

Compat shim — prefer the module-level get_utc_timestamp.