eventsource server on tornado: django support, channels, last-event-id, вот это всё
Python JavaScript
Switch branches/tags
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



tornado-sse use tornado and brukva for multichannel Server-Sent Event server. Additional it provides such thins like: eventsource polyfill, we prefer jQuery.eventsource; javascript handler for delegate SSE to jQuery events; Django management command and special Django handler.


pip install git+git://


Start server:

$ tornado_sse [--address=] [--port=8888] [--debug]

Then place static files to serve directory, or just map Nginx location to tornado_sse/static directory.


To subscribe to some channels just place them to get parameter "channels" in "sse-data" attribute of body:

    <script type="text/javascript" src="/media/tornado_sse/jquery.eventsource.js"></script>
    <script type="text/javascript" src="/media/tornado_sse/sse.js"></script>

<body sse-data="/sse/?channels=all,foo">

Intercept events

Unfortunately, many browsers catch only "onopen" and "onmessage" event, so for now I decide to make my own format of JSON for different kinds of messages:

// for redis> PUBLISH all '["message", "{\"type\": \"message\", \"your-structure\": \"Blowjob is better than no job 1\", \"user\": \"tug\"}"]'
$('body').on('sse.message', function(el, msg){

// for redis> PUBLISH all '["message", "{\"type\": \"foo\", \"other-structure\": \"Blowjob is better than no job 1\", \"user\": \"bar\"}"]'
$('body').on('', function(el, msg){

With Django


Install redis and django_sse. It is no requirements of tornado_sse.

Add "redis", "django_sse" and "tornado_sse" to INSTALLED_APPS:

### SSE ###

    'location': 'localhost:6379',
    'db': 0,
### SSE ###

tornado_sse use same settings for connection to redis as django_sse.

Sending messages from Django

Handler for Django differs from usual handler. It subscribes to channels: "%username%" and "all".

To send message you may use send_event function from django_sse.redisqueue.

I prefer to use signals for such things. So for user with login "admin" it would look something like this:

# encoding: utf-8
from django.utils import simplejson as json
from django.dispatch.dispatcher import receiver
from django.db.models.signals import post_save

from django_sse.redisqueue import send_event

from myapp.models import MyModel

@receiver(post_save, sender=MyModel)
def mymodel_post_save_notify(sender, **kwargs):
    instance = kwargs.get('instance')

    message = json.dumps({
        'type': 'foo',
        'html': instance.as_html(),

    send_event('message', message, 'admin') # named channel

    return True

Start server:

(env) ...$ python runsseserver


In HTML no need to register channels in "sse-data" because handler determines their names on the session:

    <script type="text/javascript" src="{{ STATIC_URL }}tornado_sse/jquery.eventsource.js"></script>
    <script type="text/javascript" src="{{ STATIC_URL }}tornado_sse/sse.js"></script>

<body sse-data="/sse/">

Intercept events

Use code from Standalone section.

Nginx setup

If your main server in behind Nginx you may proxy SSE like this:

location /sse/ {
    rewrite                 ^(.*)$ / break; # to root of our tornado
    proxy_buffering         off; # to push immediately
    proxy_pass    ;