Nisala
Nisala

Reputation: 1338

Using Django Channels to send info to all connected clients

I'm creating a system where the Twitter Live Streaming API gets a live stream of tweet data through given keywords. Whenever a tweet comes in, I want to send that new data over WebSockets (using Django Channels) to all connected clients. Here's my current procedure:

  1. Twitter live streaming code calls initiateHandshake() function in consumers.py whenever it gets new data
  2. Django channels sends the text "handshake" to all clients
  3. Client recieves handshake message and sends a message back
  4. The websocket.recieve function picks up this message, and, based on filter information that is stored in the client's connection session, sends back the needed data (this is why the handshake is needed - because each client has its own filter that is in its connection session)

Right now, the problem is that the "handshake" message in initiateHandshake() isn't sending. Why is this, and how can I fix it? Thank you so much! My code is below.

WebSockets is functioning correctly (If the client sends a message, I can use reply_channel to reply to it - that all works)

routing.py

from channels.routing import route
from tweetrunner.consumers import *

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

consumers.py

# In consumers.py
from channels import Group, Channel
from channels.sessions import channel_session
from .models import InputTweet
from django.shortcuts import render

# Outside world connection
def initiateHandshake():
    Group("table").send({"text": "handshake"})


# Connected to websocket.connect
@channel_session
def ws_connect(message):
    # Accept connection
    message.reply_channel.send({"accept": True})
    message.channel_session["sort"] = "none"
    # Add to group
    Group("table").add(message.reply_channel)


# Connected to websocket.receive
@channel_session
def ws_message(message):
    definition = message.content['text'][:1]

    if definition == "1":
        emotion = message.content['text'][1:]
        message.channel_session["sort"] = message.content['text'][1:]

        sendback = ""

        if emotion == 'none':
            given_tweets = InputTweet.objects.all()
            given_tweets = given_tweets[(len(given_tweets) - 1250):]
            print("before render")
            sendback = render(None, 'tweetrunner/get_table_update.html', {'given_tweets': given_tweets})
            print("rendered")
        else:
            given_tweets = InputTweet.objects.filter(emotion__startswith=emotion).order_by('score')
            given_tweets = given_tweets[(len(given_tweets) - 1250):]
            sendback = render(None, 'tweetrunner/get_table_update.html', {'given_tweets': given_tweets})

        print("about to send")
        message.reply_channel.send({
            "text": sendback.content.decode('utf-8'),
        })
        print("sent -- END CONNECTION LOGS")

    elif definition == "3":
        print("Keep alive!")

    else:

        emotion = message.channel_session["sort"]

        sendback = ""

        print("entered 2")

        if emotion == 'none':
            given_tweets = InputTweet.objects.all()
            given_tweets = given_tweets[(len(given_tweets) - 1250):]
            print("before render")
            sendback = render(None, 'tweetrunner/get_table_update.html', {'given_tweets': given_tweets})
            print("rendered")
        else:
            given_tweets = InputTweet.objects.filter(emotion__startswith=emotion).order_by('score')     
            given_tweets = given_tweets[(len(given_tweets) - 1250):]
            sendback = render(None, 'tweetrunner/get_table_update.html', {'given_tweets': given_tweets})

        print("about to send")

        #content = sendback.read()

        message.reply_channel.send({
            "text": sendback.content.decode('utf-8'),
        })

        print("sent -- END CONNECTION LOGS")


# Connected to websocket.disconnect
@channel_session
def ws_disconnect(message):
    Group("table").discard(message.reply_channel)

My code, which is not in any django app, is initializing django like this (I can access the database and use django calls, so it's working):

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

import django
django.setup()

JavaScript on client:

socket = new WebSocket("ws://" + window.location.host + "/");

socket.onmessage = function(e) {
alert("Got message: " + e.data)
    if (e.data == "handshake") {
        socket.send("2handshake");
        alert("sent");
    } else {
        document.getElementById("tweetTable").innerHTML = e.data;
        $('.tooltiphere').tooltip('remove');
        $('.tooltiphere').tooltip({delay: 10});
    }
}

Upvotes: 2

Views: 5443

Answers (1)

Raja Simon
Raja Simon

Reputation: 10305

initiateHandshake() will not sending any message when you use In-memory Channel layer.

From the doc: In-Memory layer does not support cross-process communication

Please use the other channel layer type particularly Redis channel layer. And everything will work as expected.

Upvotes: 3

Related Questions