{"id":20455379,"url":"https://github.com/alexmhack/channels_tutorial","last_synced_at":"2026-05-08T00:32:49.395Z","repository":{"id":114088285,"uuid":"146788906","full_name":"Alexmhack/channels_tutorial","owner":"Alexmhack","description":"working along django channels official tutorial and creating a chat service with chat groups","archived":false,"fork":false,"pushed_at":"2018-09-29T09:02:24.000Z","size":1645,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-08T02:14:12.033Z","etag":null,"topics":["beginner","beginner-project","channels-framework","django","django-channels-framework","django-project","python3","tutorial"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Alexmhack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-08-30T18:16:15.000Z","updated_at":"2023-08-27T01:37:05.000Z","dependencies_parsed_at":null,"dependency_job_id":"b607e4e6-7ddf-4687-b9ff-5ede1021b96b","html_url":"https://github.com/Alexmhack/channels_tutorial","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Alexmhack/channels_tutorial","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexmhack%2Fchannels_tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexmhack%2Fchannels_tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexmhack%2Fchannels_tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexmhack%2Fchannels_tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Alexmhack","download_url":"https://codeload.github.com/Alexmhack/channels_tutorial/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexmhack%2Fchannels_tutorial/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32762058,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-07T02:14:30.463Z","status":"ssl_error","status_checked_at":"2026-05-07T02:14:29.405Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["beginner","beginner-project","channels-framework","django","django-channels-framework","django-project","python3","tutorial"],"created_at":"2024-11-15T11:18:42.699Z","updated_at":"2026-05-08T00:32:49.374Z","avatar_url":"https://github.com/Alexmhack.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# channels_tutorial\nworking along django channels official tutorial and creating a chat service with chat groups\n\n# Dependencies\n\n**requirements.txt**\n```\ndjango==2.1\nchannels==2.1.3\nasgi_redis==1.4.3\n```\n\n# Installation\n\n**cmd**\n```\n\u003e pip install django\n\u003e pip install channels\n\u003e pip install asgi_redis\n```\n\nLaunch ubuntu1804 using the command ubuntu1804\n\n**Ubuntu1804**\n```\n\u003e ubuntu1804\n$ sudo apt-get install redis-server\n$ redis-server\n```\n\n**Ubuntu1804** is the ubuntu terminal and some features of ubuntu from the ubuntu app \ndonwloaded from play store, follow the instructions given in the description of the app\n\nOnce redis-server is installed you don't need to start it everytime, if an error comes on\nrunning the command ```redis-server``` that means server is already running and you can \nrestart the server using\n\n**cmd**\n```\n\u003e redis-cli shutdown\n\u003e redis-server\n```\n\n# Start project\nStart fresh django project *mysite* inside virtualenv or outside of it as we discussed in \n[django_channels github repo](https://github.com/Alexmhack/django_channels)\n\n**cmd**\n```\n\u003e django-admin startproject mysite\n\u003e cd mysite\n\u003e python manage.py startapp chat\n```\n\nStart a new app named chat and add it in your installed apps settings\n\nAdd a *index.html* file in your templates folder\n\nUsing javascript/jquery we are going to open the url for the room name entered in the input\n\n**templates/chat/index.html**\n```\n\u003c!-- SCRIPTS --\u003e\n    \u003cscript type=\"text/javascript\" charset=\"utf-8\" async defer\u003e\n        var roomName = $(\"#room-name-input\").focus();\n\n        $(\"#room-name-input\").keyup(function(e) {\n            if (e.keyCode === 13) {\n                $(\"#room-name-submit\").click();\n            }\n        });\n\n        $(\"#room-name-submit\").click(function(e) {\n            var roomName = $(\"#room-name-input\").val();\n            window.location.pathname = '/chat/' + roomName + '/';\n        })\n    \u003c/script\u003e\n```\n\nWe have used jquery but you can use plain javascript. Using the .val() function from jquery \nwe fetch the value of the input form with id *room-name-input* and then using javascript \n```window.location.pathname``` we enter the url for room name\n\nNow we have to create a view and url for that view in our chat app \n\n**chat/views.py**\n```\nfrom django.shortcuts import render\n\ndef index(request):\n\treturn render(request, 'chat/index.html', {})\n```\n\nCreate new file in chat app\n\n**chat/urls.py**\n```\nfrom django.urls import path\n\nfrom .views import index\n\nurlpatterns = [\n\tpath('', index, name='index'),\n]\n```\n\ninclude the chat app urls in main project urlconf\n\n**mysite/urls.py**\n```\nfrom django.contrib import admin\nfrom django.urls import path, include\n\nurlpatterns = [\n    path('admin/', admin.site.urls),\n    path('chat/', include('chat.urls')),\n]\n```\n\nNow let's check \n\n**mysite**\n```\n\u003e python manage.py runserver\n```\n\nEnter in anything and press enter or just hit the button and you will be taken to the\nnew url *127.0.0.1/chat/\u003cinput-entered\u003e*. \n\n# Integrating channels library\nIn the section we are going to integrate our simple non-functional django app with channels\nlibrary and make our chat rooms functional\n\nWe will be creating routes for channels just like we create urls in urlconf for our django \nproject, routes work in the same way, it tells the channels what to run when an HTTP request\nis received by channels server.\n\nCreate a new file for routing inside mysite folder where our settings.py file lies\n\n**mysite/routing.py**\n```\nfrom channels.routing import ProtocolTypeRouter\n\napplication = ProtocolTypeRouter({\n\t# (http-\u003edjango views is added by default)\n})\n```\n**[SOURCE](https://channels.readthedocs.io/en/latest/tutorial/part_1.html)**\n\nWe don't need to add our views they are added by default as the comment says\n\nNow we need to tell our django project about channels by including library inside our project\ninstalled apps settings\n\n**mysite/settings.py**\n```\nINSTALLED_APPS = [\n    'channels',\n    'chat',\n    'django.contrib.admin',\n    'django.contrib.auth',\n    'django.contrib.contenttypes',\n    'django.contrib.sessions',\n    'django.contrib.messages',\n    'django.contrib.staticfiles',\n]\n```\n\nNow for pointing channels to root configuration, edit the **mysite/settings.py** file and add\n```ASGI_APPLICATION``` variable with value a path for our routing file\n\n```\nASGI_APPLICATION = 'mysite.routing.application'\n```\n\n*mysite* is the folder, *routing* is the routing.py file we just created and application is \nwhat we added in routing file.\n\nRun the server again and you will see that channels has overtaken our default django server.\n\n```\n\u003e python manage.py runserver\n\nPerforming system checks...\n\nSystem check identified no issues (0 silenced).\nSeptember 01, 2018 - 10:24:20\nDjango version 2.0.7, using settings 'mysite.settings'\nStarting ASGI/Channels version 2.1.3 development server at http://127.0.0.1:8000/\nQuit the server with CTRL-BREAK.\n2018-09-01 10:24:20,773 - INFO - server - HTTP/2 support not enabled (install the http2 and tls Twisted extras)\n2018-09-01 10:24:20,773 - INFO - server - Configuring endpoint tcp:port=8000:interface=127.0.0.1\n2018-09-01 10:24:20,773 - INFO - server - Listening on TCP address 127.0.0.1:8000\n\n```\n\nLocate to the same url [127.0.0.1/chat](http://127.0.0.1:8000/chat/) and you should see the same\npage again, in your console you should see that channels is working finely with our project\n\n# Add room view\nIn this section we will be creating a new view for room where users can chat with each other \nwhile in the same room.\n\nCreate a new template for this view\n\n**templates/chat/room.html**\n```\n{% block script %}\n    \n    \u003cscript type=\"text/javascript\" charset=\"utf-8\" async defer\u003e\n        \n        var roomName = {{ room_name_json }};\n\n        var chatSocket = new Websocket(\n            'ws://' + window.location.host + 'ws/chat/' + roomName + '/'\n        );\n\n        chatSocket.onmessage = function(e) {\n            var data =  JSON.parse(e.data);\n            var message = data['message'];\n            $(\"#chat-log\").val() += (message  +'\\n');\n        };\n\n        chatSocket.onclose = function(e) {\n            console.log(\"chat socket closed unexpectedly\");\n        };\n\n        $(\"#chat-message-input\").focus();\n\n        $(\"#chat-message-input\").keyup(function(e) {\n            if (e.keyCode === 13) {\n                $(\"#chat-message-submit\").click();\n            }\n        });\n\n        $(\"#chat-message-submit\").click(function(e) {\n            var $messageInput = $(\"#chat-message-input\");\n            var message = $messageInput.val();\n\n            chatSocket.send(JSON.stringify({\n                'message': message\n            }));\n\n            $messageInput.val('');\n        });\n\n    \u003c/script\u003e\n\n{% endblock %}\n```\n\nWe send the context variable room_name_json from our *room_view* inside \n**chat/views.py**\n\n```\nimport json\n\nfrom django.shortcuts import render\nfrom django.utils.safestring import mark_safe\n\ndef room_view(request, room_name):\n    return render(request, 'chat/room.html', {\n        'room_name_json': mark_safe(json.dumps(room_name))\n    })\n\n```\n\n1. If chatSocket received a message then we parse the json data and store the message \nfrom it in a js variable and add the message in the textarea.\n\n2. If we close the browser then we print a message on the console.\n\n3. If user pressed enter we click the send button.\n\n4. If the send button is pressed then we fetch the entered message from the input\nand send message from the WebSocket instance and make the input field empty.\n\nAfter our view is ready we create a url for our view.\n\n**chat/urls.py**\n```\n    ...\n    path('\u003croom_name\u003e/', room_view, name='room-view'),\n```\n\n**NOTE:** '/' should be added after \u003croom_name\u003e in the url for our room_view\n\n# Channel Consumer\nNow we will create a basic consumer that accepts WebSocket connections on the path\n```ws/chat/room_name/ ``` that takes any message it receives on the WebSocket and \nechoes it back to the same WebSocket.\n\n**NOTE:** We have used a ws/ prefix for sending the web socket because using it we \ncan distinguish between the WebSocket connections from ordinary HTTP connections\n\nCreate a new file inside the chat app ```consumers.py```. Inside that file we simply\ncreate synchronous WebSocket consumer that accepts all connections, receives messages \nfrom its client, and echos those messages back to the same client. For now it does not \nbroadcast messages to other clients in the same room.\n\nWe need to create a routing configuration for tha chat app that has a route to the \nconsumer. Create a new file inside chat app **routing.py**\n\n**chat/routing.py**\n```\nfrom django.urls import path\n\nfrom .consumers import ChatConsumer\n\nwebsocket_urlpatterns = [\n    path('ws/chat/\u003croom_name\u003e/', ChatConsumer),\n]\n```\n\nThe next step is to point the root routing configuration at the chat.routing module.\n\n**mysite/routing.py**\n```\nimport chat.routing\n\nfrom channels.auth import AuthMiddlewareStack\nfrom channels.routing import ProtocolTypeRouter, URLRouter\n\napplication = ProtocolTypeRouter({\n    'websocket': AuthMiddlewareStack(\n        URLRouter(\n            chat.routing.websocket_urlpatterns\n        )\n    )\n})\n```\n\nWhat above piece of code does is, we create a new key named 'websocket' in the \nProtocolTypeRouter, any connection is made to the channels server it is inspected by\n*ProtocolTypeRouter* and if it is a WebSocket connection like **ws:// or wss://** then \nit is passed onto *AuthMiddlewareStack*.\n\nAuthMiddlewareStack provides the connection with a reference to the currently \nauthenticated user just like the django's AuthenticationMiddleware does with the \nrequest object through which we can use the request variables such as ```request.user```.\n\nAuthMiddlewareStack hands over the connection to the URLRouter which simply routes the\nHTTP path to a particular consumer based on the provided url patterns just like django\ndoes with its urls and then urls routes to particular views.\n\n**Run migrations** to apply database changes (Django’s session framework needs the \ndatabase) and then start the Channels development server:\n\nOpen [http://127.0.0.1:8000/chat/lobby/](http://127.0.0.1:8000/chat/lobby/) and\nenter any message in the input field and you should see the message echoed back to \nyou from the channels server.\n\n# Enable a channel layer\nWhen we enter a message, that message is echoed back to us and appears in chat log\nbut if open a new browser window with the same chat room then the message we have sent\ntill now don't appear in the new window, so for that we are going to create a channel\nlayer for multiple instances of channels.\n\n**What is channel layer ?**\n\nA channel layer is a form of communication system which allows multiple consumer \ninstances to talk to each other and other django parts.\n\n**What will a channel layer do ?**\n\n1. A channel is like a mailbox where everyone who has the name of the channel can\nsend messages to the channel.\n\n2. A group is a group of related channels. Anyone who has the name of the group can\nadd or remove the channels from group or send messages to all channels in the group.\n\nIn our chat application we want to have multiple instances of ChatConsumer in the same \nroom communicate with each other. To do that we will have each ChatConsumer add its \nchannel to a group whose name is based on the room name. That will allow ChatConsumers \nto transmit messages to all other ChatConsumers in the same room.\n\nWe will use a channel layer that uses redis as its backing store. To start a redis \nserver on port 6379, run the following command\n\n```\n\u003e redis-server \n```\n\nWe need to install channels_redis so that channels know how to interface with **redis**\n\n```\n\u003e pip install channels_redis\n```\n\nBefore we can use a channel layer we need to configure it. Edit the \n**mysite/settings.py** file and add ```CHANNELS_LAYER``` setting to the bottom\n\n```\n# mysite/settings.py\n# Channels\nASGI_APPLICATION = 'mysite.routing.application'\nCHANNEL_LAYERS = {\n    'default': {\n        'BACKEND': 'channels_redis.core.RedisChannelLayer',\n        'CONFIG': {\n            \"hosts\": [('127.0.0.1', 6379)],\n        },\n    },\n}\n```\n\nFor checking if channel layer can communicate with redis. Start a django shell and run\n\n```\n.../mysite\u003e python manage.py shell\n\n\u003e\u003e\u003e import channels.layers\n\u003e\u003e\u003e channel_layer = channels.layers.get_channel_layer()\n\u003e\u003e\u003e from asgiref.sync import async_to_sync\n\u003e\u003e\u003e async_to_sync(channel_layer.send)('test_channel', {'type': 'hello'})\n\u003e\u003e\u003e async_to_sync(channel_layer.receive)('test_channel')\n{'type': 'hello'}\n```\n\nType Control-D to exit the Django shell.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexmhack%2Fchannels_tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexmhack%2Fchannels_tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexmhack%2Fchannels_tutorial/lists"}