Django Server Push Method
Asked Answered
F

2

5

I developed a Django application which requires the server push (or comet) for the further enhancement. I first had successfully implemented the server push using the "orbited" which worked great in all the major browsers except the IE (yeah I know... this IE is screwing my life once again). Although the significance of the IE has been reduced greatly, I would still love to implement the server push that will work in ALL major platforms.

I have been googling for days and here are some options I found.

  1. Using evserver (https://code.google.com/p/evserver/)
  2. Using Django + Tornado framework

It seems like using the Django + Tornado platform is more ideal in the long run, but I couldn't really find a good example from which I can learn how to implement the server push combining two frameworks. The only example I found was

django-tornado-demo (https://github.com/bdarnell/django-tornado-demo/tree/master/testsite)

However, I am not sure if this project even handles the server push mechanism or otherwise, lacks some explanation.

Can anybody please direct me to a good example of the demo project that combines Django and Tornado together and actually implements the server push mechanism? Also, any information regarding this topic will be highly appreciated.

Thank you very much in advance.

Frumenty answered 25/5, 2013 at 0:14 Comment(0)
B
6

SockJS is the way to go: https://github.com/mrjoes/sockjs-tornado

First, make your environment ready:

pip install sockjs-tornado

Second, you have to setup Tornado:

application = django.core.handlers.wsgi.WSGIHandler()
container = tornado.wsgi.WSGIContainer(application)


tornado_app = tornado.web.Application(
    EchoSockjsRouter('/websocket')+
    [
        ('/source/([^/]+)', SourceHandler),
        ('.*', tornado.web.FallbackHandler, dict(fallback=container)),
    ]
)

HTTPServer(tornado_app).listen(port)
tornado.ioloop.IOLoop.instance().start()

'/source' is a Request handler (I use it for async with @gen.engine), '.*' works for Django, and EchoSockjsRouter is what you want:

from sockjs.tornado import SockJSRouter, SockJSConnection

class EchoWebSocket(SockJSConnection):
  def on_open(self, request):
      print "sockjs: open"

  def on_message(self, data):
      print "data: %r" % (data,)
      self.send(data)

  def on_comment(self, data):
      print "data: %r" % (data,)
      self.send(data)

  def on_close(self):
      print "sockjs: close"

def EchoSockjsRouter(prefix):
    return SockJSRouter(EchoWebSocket, prefix).urls

After that, you will need to setup the UI (I am using SockJS client, version 0.3.4, http://sockjs.org, MIT License):

<script src="<SockJS Javascript>"></script>
<script>
    socket = new SockJS('http://localhost:8000/websocket');
    socket.onmessage = function(e) {
        console.log(e.data);
    };
    socket.onclose = function() {
        console.log('closed :(');
    };
    socket.onopen = function() {
        console.log('opened :>');
        letTheMadnessBegin();
    };

    function letTheMadnessBegin() {
        // silly, but you get the idea
        socket.send(JSON.stringify({
            name: $('#name').text(),
            message: $('input').val()
        }));
    }
<script>

Well, you can make the script pretty inside $(function(){})... but besides that, you are ready to go: http://grab.by/mSv6, http://grab.by/mSuU (sorry for the 404, it is to make it realistic O.o). I took this pattern from: https://idea.popcount.org/2012-09-21-django-with-sockjs/

Please note that I tried with Socketio, Tornado WebSocket and some others. However SocketJS was incredibly straight-forward.

Regards.

Bickerstaff answered 25/5, 2013 at 6:33 Comment(4)
Thank you very much Ericson. Your answer and all the references helped me moving on toward the right direction. I haven't yet had a chance to actually implement this with my application, but I now have much clearer idea what to do. Thank you again.Frumenty
I finally implemented SockJS with my Django application and just wanted to follow up for anybody who may visit this page in the future seeking the help with the server push. SockJS is very straight forward, easily implementable, and works like a charm at all the major browsers I had tested. As Ericson pointed out, SockJS is the way to go!Frumenty
I'm looking for where in this example the server initiates a message to all the clients (that is, initiates a server push). Is it here somewhere? I see where a client's message gets rebroadcast to other connected clients, but not server initiated messages.Nickienicklaus
If I am not wrong, @npskirk, what you need are channels. You can create one and use it to send messages for subscribers.Bickerstaff
G
1

There's also Socket.IO, you can use it with gevent-socketio/django-socketio with Django. (API-wise pretty similar to the SockJS examples, maybe https://mcmap.net/q/477465/-sockjs-or-socket-io-worth-to-recode-ajax-based-page-closed helps)

Gawlas answered 25/5, 2013 at 11:28 Comment(1)
Thank you Bernhard for the references. I'll take a look into the Socket.IO as well.Frumenty

© 2022 - 2024 — McMap. All rights reserved.