This package provides Rails Action Cable support to Django Channels.
Bring Rails ActionCable to Django
Please make sure Django channels is already working in Django project before installing this package.
$ pip install django-actioncableIn the asgi.py, we have code like this
import os
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from django_app.core import routing
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_app.settings")
application = ProtocolTypeRouter(
    {
        "http": get_asgi_application(), 
        "websocket": URLRouter(routing.urlpatterns)
    }
)Notes:
- The websocketprotocol would be handled byURLRouter(routing.urlpatterns)
In the routing file, we add below code:
from actioncable import ActionCableConsumer
urlpatterns = [
    path("cable", ActionCableConsumer.as_asgi()),
]Notes:
- So all the Websocket requests sent to ws://localhost:8000/cablewould be handled byActionCableConsumer
- The ActionCableConsumerwould then dispatch the request to the corresponding channel class.
We can add below code to the routing file to register the channel class.
from actioncable import ActionCableConsumer, CableChannel, cable_channel_register
@cable_channel_register
class ChatChannel(CableChannel):
    def __init__(self, consumer: ActionCableConsumer, identifier_key, params=None):
        self.params = params if params else {}
        self.identifier_key = identifier_key
        self.consumer = consumer
        self.group_name = None
    async def subscribe(self):
        self.group_name = f"chat_{self.params['pk']}"
        await self.consumer.subscribe_group(self.group_name, self)
    async def unsubscribe(self):
        await self.consumer.unsubscribe_group(self.group_name, self)- We create a ChatChannel, which inherits from theCableChannel.
- The cable_channel_registerdecorator would register theChatChannelclass to theActionCableConsumer.
- In the subscribecallback method, we get the room pk from theself.paramsdict and subscribe the channel to the groupchat_{pk}.
- In the unsubscribecallback method, we unsubscribe the channel from the group.
<!DOCTYPE html>
<html>
<head>
  <title>ActionCable Example</title>
</head>
<body>
<div id="messages"></div>
<script src="https://cdn.jsdelivr.net/npm/@rails/[email protected]/app/assets/javascripts/actioncable.js"></script>
<script>
  document.addEventListener("DOMContentLoaded", function () {
    // Create a consumer object to connect to the ActionCable server
    const cable = ActionCable.createConsumer();
    // Define a channel and its corresponding functions
    const channel = cable.subscriptions.create({channel: "ChatChannel", pk: "1"}, {
      connected() {
        console.log("Connected to the chat channel.");
      },
      disconnected() {
        console.log("Disconnected from the chat channel.");
      },
      received(data) {
        // Display the received message
        const messagesDiv = document.getElementById("messages");
        const messageDiv = document.createElement("div");
        messageDiv.innerText = data;
        messagesDiv.appendChild(messageDiv);
      }
    });
  });
</script>
</body>
</html>Notes:
- We use the ActionCable.createConsumer()to create a consumer object to connect to the ActionCable server.
- The channeisChatChannel, so theChatChannelwe just created will be used to handle the request.
- In the client, we can pass room pk to the ChatChannelbypk: "1", and in the backend we can get it in theself.params
- In this case, the channel will subscribeto thechat_1group.
Launch Django shell, and run below code:
from actioncable import cable_broadcast
cable_broadcast("chat_1", message="Hello World")You should be able to see the message appear on the web page.
cable_broadcast is a wrapper of Django Channel async_to_sync(channel_layer.group_send) method call, we can use it in Django view or external process such as Celery worker.
The message value can also be Python dict, and in javascript we can get it in the data parameter of the received callback method.