22.6. Django Channels

Django Channels is a project that takes Django and extends its abilities beyond HTTP - to handle WebSockets, chat protocols, IoT protocols, and more. It's built on a Python specification called ASGI.


22.6.1. Install

Run command in system terminal:

$ python -m pip install 'channels[daphne]'

22.6.2. Settings

Append to myproject/settings.py:

INSTALLED_APPS += ['daphne', 'chat']
ASGI_APPLICATION = 'myproject.asgi.application'
    'default': {
        'BACKEND': 'channels.layers.InMemoryChannelLayer',


During development you can use InMemoryChannelLayer config. For production use RedisChannelLayer (see below).

22.6.3. Template

File chat/templates/chat/index.html:

<!DOCTYPE html>
<html lang="en">
    <meta charset="utf-8">

<form id="form">
    <input type="text" id="message" name="message" placeholder="Type your message here">
    <button type="submit">Send</button>

<div id="messages">

    document.addEventListener('DOMContentLoaded', () => {

        const ws = new WebSocket('ws://{{ request.get_host }}/ws/chat/');
        ws.onmessage = (response) => {
            data = JSON.parse(response.data);
            switch (data.type) {
                case 'system': console.log(data.value); break;
                case 'message': onMessage(data.value); break;

        onMessage = (msg) => {
            let history = document.getElementById('history');
            let message = document.createElement('p');
            message.textContent = msg;

        const form = document.querySelector('form');
        form.addEventListener('submit', (event) => {
                type: 'message',
                value: form.message.value



22.6.4. View

Append to file shop/views.py:

from django.shortcuts import render

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

22.6.5. URLs

Append to file myproject/urls.py:

from chat.views import chat

urlpatterns += [path('chat/', chat, name='chat')]

22.6.6. Consumers

File chat/consumers.py:

from channels.generic.websocket import JsonWebsocketConsumer
from asgiref.sync import async_to_sync

class ChatConsumer(JsonWebsocketConsumer):
    def connect(self):
        self.room_group_name = 'chat'
        func = async_to_sync(self.channel_layer.group_add)
        func(self.room_group_name, self.channel_name)
            'type': 'system',
            'value': 'connected',

    def receive_json(self, content):
        func = async_to_sync(self.channel_layer.group_send)
        func(self.room_group_name, {
            'type': 'handle',
            'value': content['value'],

    def handle(self, event):
            'type': 'message',
            'value': event['value'],

    def disconnect(self, close_code):
            'type': 'system',
            'value': 'disconnected',

22.6.7. Routing

File chat/routing.py:

from django.urls import re_path
from .consumers import ChatConsumer

websocket_urlpatterns = [
    re_path(r'ws/chat/', ChatConsumer.as_asgi())

22.6.8. ASGI

  • channels.auth.AuthMiddlewareStack - Uses Django session authentication

  • It is not needed for public channels

Modify myproject/asgi.py:

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

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')

application = ProtocolTypeRouter({
    'http': get_asgi_application(),
    'websocket': AuthMiddlewareStack(

22.6.9. Redis

  • For production environment

Run command in system terminal:

$ python -m pip install channels_redis

Append to myproject/settings.py:

    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [
                ('localhost', 6379),

22.6.10. Further Reading