Django – Simple channels Example

Django is a great python web framework for server side. If we want to communicate with the client it can be done using the request-response model and also using a web socket especially when we want to send push notifications to the client.

This is a very simple example of how to create and communicate using a channel (web socket) it can be used as a starter for any web application with channels need

First step is to create and activate virtual environment

# virtualenv -p /usr/local/bin/python3 env
# source env/bin/activate

Install django and create a new app

# pip install django
# django-admin startproject chantest
# cd chantest/
# python manage.py startapp example

install channels for web sockets support and asgi_redis for using redis-server as a backend

# pip install channels asgi_redis

Add the channels and example to the installed apps (in settings.py)

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'channels',
    'example',
]

Add the channel configuration at the end of the settings.py file:

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'asgi_redis.RedisChannelLayer',
        'CONFIG': {
            'hosts': [('localhost', 6379)],
        },
        'ROUTING': 'chantest.routing.channel_routing',
    }
}

It defines the backend as redis server and set the port

install redis server

For Mac
# brew install redis 

For Linux (ubuntu)
# sudo apt-get install redis-server

start the redis server

# redis-server

run migrate and the server

# python manage.py migrate
# python manage.py runserver

Edit the file urls.py:

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include('example.urls', namespace='example')),
]

Add urls.py file to the folder example

from django.conf.urls import url
from example import views

urlpatterns = [
    url(r'^$', views.HomePageView.as_view()),
]

Add a simple view to views.py file:

# Create your views here.
from django.shortcuts import render
from django.views.generic import TemplateView


# Create your views here.
class HomePageView(TemplateView):
    def get(self, request, **kwargs):
        return render(request, 'index.html', context=None)

Add a template folder (below example) and add index.html file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
      <script>
    var socket = new WebSocket('ws://' + window.location.host + '/stocks/');

    socket.onopen = function open() {
      console.log('WebSockets connection created.');
    };

    socket.onmessage = function message(event) {
      console.log("data from socket:" + event.data);
      lbl.innerText = event.data;
    };

    if (socket.readyState == WebSocket.OPEN) {
      socket.onopen();
    }
    function start()
    {
      socket.send('start');
    }
    function stop() {
        socket.send('stop');
    }
  </script>

</head>
<body>
<h2>hello</h2>

<button onclick="start()">Start</button>
<button onclick="stop()">Stop</button>

<label id="lbl">Data</label>
</body>
</html>

In the above code we open a web socket on load and connect to the server. We also added 2 buttons to send ‘start’ and ‘stop’ command to the socket and label for data received

Add the file routing.py to chantest directory: (as we declared it in settings.py file)

from channels.routing import route
from example.consumers import ws_connect, ws_disconnect, ws_message


channel_routing = [
    route('websocket.connect', ws_connect),
    route('websocket.disconnect', ws_disconnect),
    route("websocket.receive", ws_message),
]

Add consumer.py file to example directory:

from channels import Group
import threading
import random

def sendmsg(num):
    Group('stocks').send({'text':num})

t = 0

def periodic():
    global t;
    n = random.randint(10,200);
    sendmsg(str(n))
    t = threading.Timer(5, periodic)
    t.start()

def ws_message(message):
    global t
    print(message.content['text'])
    if ( message.content['text'] == 'start'):
        periodic()
    else:
        t.cancel()

def ws_connect(message):
    Group('stocks').add(message.reply_channel)
    Group('stocks').send({'text':'connected'})


def ws_disconnect(message):
    Group('stocks').send({'text':'disconnected'})
    Group('stocks').discard(message.reply_channel)

Test your work – click on start to see the generated numbers in the label and click on stop to disable it

You can download the code from github

 

 

Tagged ,

13 thoughts on “Django – Simple channels Example

  1. Thanks Liran B.H

  2. Getting the following error when I do runserver
    CommandError: You have not set ASGI_APPLICATION, which is needed to run the server.

    1. Did you find a solution?

  3. Is it for Channels 1.x? Do you plan to update it for Channels 2?

  4. yOU SHOULD BETTER PROOFREAD YOUR ARTICLES BEFORE YOU PUBLISH, THERE ARE SEMICOLONS IN THE PYTHON CODEBLOCKS 😉

    1. Oops, sorry, caps. The comment section makes everything capital letter, so I couldn’t see how it would end up 🙂

    2. NO PROBLEM WITH SEMICOLONS IN PYTHON
      it is C/C++/Java/C# friendly

  5. i can it work on django1.9
    and python 2.7

    1. is it it work on django1.9
      and python 2.7

  6. Increase Likes, auto liker, Photo Liker, Photo Auto Liker, Autolike International, autolike, Autoliker, Autolike, Autoliker, Auto Liker, ZFN Liker, Auto Like, Status Auto Liker, autoliker, Working Auto Liker, Status Liker, auto like

  7. […] Django Simple Channels Example (devarea.com) […]

  8. Unable to run
    django.core.exceptions.ImproperlyConfigured: Cannot import ASGI_APPLICATION module ‘chantest.routing’

Comments are closed.