# README
This package provides Rails Action Cable support to Django Channels.
## Install
Please make sure [Django channels](https://channels.readthedocs.io/) is already working in Django project before installing this package.
```bash
$ pip install django-actioncable
```
In the `asgi.py`, we have code like this
```python
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:
1. The `websocket` protocol would be handled by `URLRouter(routing.urlpatterns)`
In the routing file, we add below code:
```python
from actioncable import ActionCableConsumer
urlpatterns = [
path("cable", ActionCableConsumer.as_asgi()),
]
```
Notes:
1. So all the Websocket requests sent to `ws://localhost:8000/cable` would be handled by `ActionCableConsumer`
2. The `ActionCableConsumer` would then dispatch the request to the corresponding channel class.
We can add below code to the routing file to register the channel class.
```python
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)
```
1. We create a `ChatChannel`, which inherits from the `CableChannel`.
2. The `cable_channel_register` decorator would register the `ChatChannel` class to the `ActionCableConsumer`.
3. In the `subscribe` callback method, we get the room pk from the `self.params` dict and subscribe the channel to the group `chat_{pk}`.
4. In the `unsubscribe` callback method, we unsubscribe the channel from the group.
## HTML
```html
<!DOCTYPE html>
<html>
<head>
<title>ActionCable Example</title>
</head>
<body>
<div id="messages"></div>
<script src="https://cdn.jsdelivr.net/npm/@rails/actioncable@7.1.2/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:
1. We use the `ActionCable.createConsumer()` to create a consumer object to connect to the ActionCable server.
2. The `channe` is `ChatChannel`, so the `ChatChannel` we just created will be used to handle the request.
3. In the client, we can pass room pk to the `ChatChannel` by `pk: "1"`, and in the backend we can get it in the `self.params`
4. In this case, the channel will `subscribe` to the `chat_1` group.
## Test
Launch Django shell, and run below code:
```python
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.
Raw data
{
"_id": null,
"home_page": "https://github.com/AccordBox/django-actioncable",
"name": "django-actioncable",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "",
"keywords": "",
"author": "Michael Yin",
"author_email": "michaelyin@accordbox.com",
"download_url": "https://files.pythonhosted.org/packages/a8/d7/e203e37e9cc574c58bb4e824897743db985038602c2acaa1ecda2512a893/django_actioncable-1.0.4.tar.gz",
"platform": null,
"description": "# README\n\nThis package provides Rails Action Cable support to Django Channels.\n\n## Install\n\nPlease make sure [Django channels](https://channels.readthedocs.io/) is already working in Django project before installing this package.\n\n```bash\n$ pip install django-actioncable\n```\n\nIn the `asgi.py`, we have code like this\n\n```python\nimport os\n\nfrom channels.routing import ProtocolTypeRouter, URLRouter\nfrom django.core.asgi import get_asgi_application\n\nfrom django_app.core import routing\n\nos.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"django_app.settings\")\n\napplication = ProtocolTypeRouter(\n {\n \"http\": get_asgi_application(), \n \"websocket\": URLRouter(routing.urlpatterns)\n }\n)\n```\n\nNotes:\n\n1. The `websocket` protocol would be handled by `URLRouter(routing.urlpatterns)`\n\nIn the routing file, we add below code:\n\n```python\nfrom actioncable import ActionCableConsumer\n\n\nurlpatterns = [\n path(\"cable\", ActionCableConsumer.as_asgi()),\n]\n```\n\nNotes:\n\n1. So all the Websocket requests sent to `ws://localhost:8000/cable` would be handled by `ActionCableConsumer`\n2. The `ActionCableConsumer` would then dispatch the request to the corresponding channel class.\n\nWe can add below code to the routing file to register the channel class.\n\n```python\nfrom actioncable import ActionCableConsumer, CableChannel, cable_channel_register\n\n\n@cable_channel_register\nclass ChatChannel(CableChannel):\n\n def __init__(self, consumer: ActionCableConsumer, identifier_key, params=None):\n self.params = params if params else {}\n self.identifier_key = identifier_key\n self.consumer = consumer\n self.group_name = None\n\n async def subscribe(self):\n self.group_name = f\"chat_{self.params['pk']}\"\n await self.consumer.subscribe_group(self.group_name, self)\n\n async def unsubscribe(self):\n await self.consumer.unsubscribe_group(self.group_name, self)\n```\n\n1. We create a `ChatChannel`, which inherits from the `CableChannel`. \n2. The `cable_channel_register` decorator would register the `ChatChannel` class to the `ActionCableConsumer`.\n3. In the `subscribe` callback method, we get the room pk from the `self.params` dict and subscribe the channel to the group `chat_{pk}`. \n4. In the `unsubscribe` callback method, we unsubscribe the channel from the group.\n\n## HTML\n\n```html\n<!DOCTYPE html>\n<html>\n<head>\n <title>ActionCable Example</title>\n</head>\n<body>\n<div id=\"messages\"></div>\n\n<script src=\"https://cdn.jsdelivr.net/npm/@rails/actioncable@7.1.2/app/assets/javascripts/actioncable.js\"></script>\n<script>\n document.addEventListener(\"DOMContentLoaded\", function () {\n // Create a consumer object to connect to the ActionCable server\n const cable = ActionCable.createConsumer();\n\n // Define a channel and its corresponding functions\n const channel = cable.subscriptions.create({channel: \"ChatChannel\", pk: \"1\"}, {\n connected() {\n console.log(\"Connected to the chat channel.\");\n },\n\n disconnected() {\n console.log(\"Disconnected from the chat channel.\");\n },\n\n received(data) {\n // Display the received message\n const messagesDiv = document.getElementById(\"messages\");\n const messageDiv = document.createElement(\"div\");\n messageDiv.innerText = data;\n messagesDiv.appendChild(messageDiv);\n }\n });\n });\n</script>\n\n</body>\n</html>\n```\n\nNotes:\n\n1. We use the `ActionCable.createConsumer()` to create a consumer object to connect to the ActionCable server.\n2. The `channe` is `ChatChannel`, so the `ChatChannel` we just created will be used to handle the request.\n3. In the client, we can pass room pk to the `ChatChannel` by `pk: \"1\"`, and in the backend we can get it in the `self.params`\n4. In this case, the channel will `subscribe` to the `chat_1` group.\n\n## Test\n\nLaunch Django shell, and run below code:\n\n```python\nfrom actioncable import cable_broadcast\n\ncable_broadcast(\"chat_1\", message=\"Hello World\")\n```\n\nYou should be able to see the message appear on the web page.\n\n`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.\n\nThe `message` value can also be Python dict, and in javascript we can get it in the `data` parameter of the `received` callback method.\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "This package provides Rails Action Cable support to Django",
"version": "1.0.4",
"project_urls": {
"Changelog": "https://github.com/AccordBox/django-actioncable/releases",
"Homepage": "https://github.com/AccordBox/django-actioncable"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "63b872af5276ea41e4c60cc785e878f121b36a07c3658867c81ae7294dec53b3",
"md5": "b48b5233cfaa6736c7cad3fd19f4141c",
"sha256": "c7becceb29a6748266a8b35b426103506549d4d759c031ef0468a09f61161524"
},
"downloads": -1,
"filename": "django_actioncable-1.0.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b48b5233cfaa6736c7cad3fd19f4141c",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 5655,
"upload_time": "2024-01-18T07:34:57",
"upload_time_iso_8601": "2024-01-18T07:34:57.868373Z",
"url": "https://files.pythonhosted.org/packages/63/b8/72af5276ea41e4c60cc785e878f121b36a07c3658867c81ae7294dec53b3/django_actioncable-1.0.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "a8d7e203e37e9cc574c58bb4e824897743db985038602c2acaa1ecda2512a893",
"md5": "70c17b8234fc78a9efce33bb0486e927",
"sha256": "0b24111b27e7aa6ed3cad1acaca47b3537dc73d49c266c5c4b2b42b079c2d6bb"
},
"downloads": -1,
"filename": "django_actioncable-1.0.4.tar.gz",
"has_sig": false,
"md5_digest": "70c17b8234fc78a9efce33bb0486e927",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 4497,
"upload_time": "2024-01-18T07:34:59",
"upload_time_iso_8601": "2024-01-18T07:34:59.040963Z",
"url": "https://files.pythonhosted.org/packages/a8/d7/e203e37e9cc574c58bb4e824897743db985038602c2acaa1ecda2512a893/django_actioncable-1.0.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-01-18 07:34:59",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "AccordBox",
"github_project": "django-actioncable",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "django-actioncable"
}