Home/Channel Layers In Django – Auriga

Channel Layers In Django – Auriga

Published On: 27 April 2021.By .
  • General

Channels Layers In Django

Channel Layers allow us to create interaction between different instances of an application, mostly used to create real-time applications, we can say it’s an alternative to sockets. Channel Layers are purely async interfaces (for both sender and receiver), you have to wrap them in a wrapper container if you want them to behave synchronously.

Channel Layer configurations

You can configure Channel Layer via CHANNEL_LAYERS in the settings file. you can get the default channel layer in your project with

channels.layers.get_channel_layer()

In case are in consumer you can get it with

self.channel_layer

Redis Channel Layer – (Channels Layers in Django)

channel_redis is the only official Django-maintained channel layer support for production use. Redis Channel layer uses redis as its backing store. you can configure it by putting the below configurations in your settings file.

Code Example, when Redis is running on localhost (127.0.0.2) and on port (6379

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("127.0.0.1", 6379)],
        },
    },
}

In Memory Channel Layer- (Channels Layers in Django)

we can also use channels with In-memory store by using In-Memory Channel Layer, you can configure it by putting the following piece of code in your settings file.

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels.layers.InMemoryChannelLayer"
    }
}

Implementation of Channel layers with an example

for more understanding with Channel layers in Django let’s discuss and Chat room example.

Let’s create an app for Chat room.

python3 manage.py startapp chat

chat/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py

adding creating app to installed_apps in settings file

# mysite/settings.py
INSTALLED_APPS = [
    'chat',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

creating a template as a output view.

chat/
    __init__.py
    templates/
        chat/
            index.html
    views.py

put the following code in chat/templates/chat/index.html

<!-- chat/templates/chat/index.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Chat Rooms</title>
</head>
<body>
    What chat room would you like to enter?<br>
    <input id="room-name-input" type="text" size="100"><br>
    <input id="room-name-submit" type="button" value="Enter">

    <script>
        document.querySelector('#room-name-input').focus();
        document.querySelector('#room-name-input').onkeyup = function(e) {
            if (e.keyCode === 13) {  // enter, return
                document.querySelector('#room-name-submit').click();
            }
        };

        document.querySelector('#room-name-submit').onclick = function(e) {
            var roomName = document.querySelector('#room-name-input').value;
            window.location.pathname = '/chat/' + roomName + '/';
        };
    </script>
</body>
</html>

now rendering template as view by adding following code in chat/views.py

# chat/views.py
from django.shortcuts import render

def index(request):
    return render(request, 'chat/index.html')

URL configurations for the above-rendered view by putting the following code in chat/urls.py

# chat/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
]

Including Chat app URL configurations to main URL configurations

# mysite/urls.py
from django.conf.urls import include
from django.urls import path
from django.contrib import admin

urlpatterns = [
    path('chat/', include('chat.urls')),
    path('admin/', admin.site.urls),
]

Integrating Channel library

# mysite/asgi.py
import os

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

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")

application = ProtocolTypeRouter({
  "http": get_asgi_application(),
  "websocket": AuthMiddlewareStack(
        URLRouter(
            chat.routing.websocket_urlpatterns
        )
    ),
})

configuring channels by putting the following code in my settings file.

# mysite/settings.py
INSTALLED_APPS = [
    'channels',
    'chat',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

# mysite/settings.py
# Channels
ASGI_APPLICATION = 'mysite.asgi.application'

adding chat room template in chat/templates/chat/room.html file

chat/
    __init__.py
    templates/
        chat/
            index.html
            room.html
    urls.py
    views.py

<!-- chat/templates/chat/room.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Chat Room</title>
</head>
<body>
    <textarea id="chat-log" cols="100" rows="20"></textarea><br>
    <input id="chat-message-input" type="text" size="100"><br>
    <input id="chat-message-submit" type="button" value="Send">
    {{ room_name|json_script:"room-name" }}
    <script>
        const roomName = JSON.parse(document.getElementById('room-name').textContent);

        const chatSocket = new WebSocket(
            'ws://'
            + window.location.host
            + '/ws/chat/'
            + roomName
            + '/'
        );

        chatSocket.onmessage = function(e) {
            const data = JSON.parse(e.data);
            document.querySelector('#chat-log').value += (data.message + '\n');
        };

        chatSocket.onclose = function(e) {
            console.error('Chat socket closed unexpectedly');
        };

        document.querySelector('#chat-message-input').focus();
        document.querySelector('#chat-message-input').onkeyup = function(e) {
            if (e.keyCode === 13) {  // enter, return
                document.querySelector('#chat-message-submit').click();
            }
        };

        document.querySelector('#chat-message-submit').onclick = function(e) {
            const messageInputDom = document.querySelector('#chat-message-input');
            const message = messageInputDom.value;
            chatSocket.send(JSON.stringify({
                'message': message
            }));
            messageInputDom.value = '';
        };
    </script>
</body>
</html>

rendering chat room view in chat/views.py

# chat/views.py
from django.shortcuts import render

def index(request):
    return render(request, 'chat/index.html', {})

def room(request, room_name):
    return render(request, 'chat/room.html', {
        'room_name': room_name
    })

adding URL for chat room in URL file( chat/urls.py)

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('<str:room_name>/', views.room, name='room'),
]

now we have to create a consumer to control this  whole process as in the chat/consumers.py file

chat/
    __init__.py
    consumers.py
    templates/
        chat/
            index.html
            room.html
    urls.py
    views.py

import json
from channels.generic.websocket import WebsocketConsumer

class ChatConsumer(WebsocketConsumer):
    def connect(self):
        self.accept()

    def disconnect(self, close_code):
        pass

    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']

        self.send(text_data=json.dumps({
            'message': message
        }))

as to configure above consumer with and URL we have to define URL routing in chat/routing.py file

chat/
    __init__.py
    consumers.py
    routing.py
    templates/
        chat/
            index.html
            room.html
    urls.py
    views.py

from django.urls import re_path

from . import consumers

websocket_urlpatterns = [
    re_path(r'ws/chat/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
]

here we go now run command python manage.py runserver  and hit URL  “/chat-room/”,  by doing so you can visit a chat room, if you are opening the same URL in two different tabs, you are able to pass the messages in between two tabs without page load.

 

Related content

We Love Conversations

Say Hello
Go to Top