Git Product home page Git Product logo

django-sse's Introduction

django-sse

Warning: this package is now unmantained because django is not the optimal platform for persistent connections. I strongly recommend use anything like tornado or asyncio with python3 for this purpose.

Django integration with Server-Sent Events. (http://www.html5rocks.com/en/tutorials/eventsource/basics/) (https://developer.mozilla.org/es/docs/Server-sent_events/utilizando_server_sent_events_sse)

This django application uses the module sse, simple python implementation of sse protocol.

Introduction

Is very similar to Django's generic views.

django-sse exposes a generic view for implement the custom logic of the data stream. Additionally, it exposes some helper views for simple enqueuing messages for a client, using redis or rabbitmq(not implemented).

NOTE: it strongly recomended expose this views with gevent pywsgi server, because every connection is permanent blocking stream.

Implementing own view with sample stream

The idea is to create a stream of data to send the current timestamp every 1 second to the client:

from django_sse.views import BaseSseView
import time

class MySseStreamView(BaseSseView):
    def iterator(self):
        while True:
            self.sse.add_message("time", str(time.time()))
            yield
            time.sleep(1)

The iterator() method must be a generator of data stream. The view has sse object, for more information, see sse module documentation.

The acomulated data on sse is flushed to the client every iteration (yield statement). You can flush the buffer, sometimes as you need.

Using a redis as message queue for push messages to client

django-sse currently implements a redis helper for simple enqueuing messages for push to a clients. For use it, the first step is a url declaration:

from django.conf.urls import patterns, include, url
from django_sse.redisqueue import RedisQueueView

urlpatterns = patterns('',
    url(r'^stream1/$', RedisQueueView.as_view(redis_channel="foo"), name="stream1"),
)

This, on new connection is created, opens connection to redis and subscribe to a channel. On new messages received from redis, it flushes theese to client.

And the second step, your can push messages to the queue in any other normal django views with a simple api:

from django.http import HttpResponse
from django_sse.redisqueue import send_event

def someview(request):
    send_event("myevent", "mydata", channel="foo")
    return HttpResponse("dummy response")

RedisQueueView precises of redis, put your connection params on your settings.py:

REDIS_SSEQUEUE_CONNECTION_SETTINGS = {
    'location': 'localhost:6379',
    'db': 0,
}

Can subscribe to a channel dynamically with some parameter on url?

Yes, you need create a subclass of RedisQueueView and overwrite the method get_redis_channel. Example:

# urls.py
urlpatterns = patterns('',
    url(r'^sse/(?P<channel>\w+)/$', MyRedisQueueView.as_view(redis_channel="foo"), name="stream1"),
)

class MyRedisQueueView(RedisQueueView):
    def get_redis_channel(self):
        return self.kwargs['channel'] or self.redis_channel

Contributors:

License

BSD License

django-sse's People

Contributors

astagi avatar aztrock avatar fcurella avatar lukaszb avatar streeter avatar sv1jsb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-sse's Issues

Difference between pip and git code

Hi,

I know that do not update the code since 2014, but I just want to tell you that the code in the final package of pip (0.4.1) is different that you got in the git (0.4.1), although both claim to be the same version.

Thank you.

Allow using django database as message queue

For small sites (which I guess is most) it'd make sense to not relying on Redis (or RabbitMQ) as a queue. Kinda like Celery allows you to use the database you already have for django.

Ofc, it would have to poll, but that's okay for such a simple deployment.

It would make developing sites simpler too, hopefully. WDYT?

Runserver doesn't reload with an active SSE connection

Longpolling seems to prevent runserver from restarting cleanly during development (using Django 1.4). It'd be nice to have it kill open connections so it can reload properly. Not sure if this is an issue upstream or something that django-sse can workaround.

is not possible to redirect the project?

no possibility of directing the project to asyncio? or asyncio-sse?

can use realtime with django in great measure, and using async uwsgi or gunicorn workers.

Long polling / streaming updates

Having read your code, which is very nice otherwise, I notice a lack of yield statements which would be required to do long polling. Right now, it seems that the connection is closed after each response (whether a message is returned or not) - regardless of whether there's new data or not.

This leaves the major advantage of SSE unused. Especially for mobile devices creating TCP connections all the time can proof to be a considerable load. Also, it can slow down the interaction with the server.

Do note that I might have been misreading your code - haven't found the time to use it yet. Then again, I might opt to use your code in which I would implement the requested functionality myself.

Reference: http://stackoverflow.com/questions/2922874/how-to-stream-an-httpresponse-with-django

cleanup connections

Hi,
I really find this project interesting and I am experimenting a bit around with redis pubsub.
I understand that using pub sub the webserver will keep an open connection with the browser and will use one of the connections from the redis pool to subscribe to the desired channel.
What is bothering me is that the webserver will not notice when a browser drops a connection, for that reason that specific redis connection will be kept open forever and at some point the pool will run out of connections and start to complain (or the connection count will leak forever)
Do you have any idea about some way to properly address this problem ?

redis memory usage

Hi all, did someone run django-sse in a long time?
I got redis memory over 1G after run in 24h,
and this maked redis-server killed itself.

How to config redis for django-sse ?

redisqueue error

In redis

PUBLISH sse '1'
[15/Mar/2014 19:16:49] "GET /events2/ HTTP/1.1" 200 0
Traceback (most recent call last):
  File "/usr/lib/python3.3/wsgiref/handlers.py", line 138, in run
    self.finish_response()
  File "/usr/lib/python3.3/wsgiref/handlers.py", line 179, in finish_response
    for data in self.result:
  File "/opt/repositories/billing/local/lib/python3.3/site-packages/django/http/response.py", line 295, in __next__
    return self.make_bytes(next(self._iterator))
  File "../django_sse/views.py", line 26, in _iterator
    for subiterator in self.iterator():
  File "../django_sse/redisqueue.py", line 69, in iterator
    event, data = json.loads(message['data'].decode('utf-8'))
TypeError: 'int' object is not iterable
[15/Mar/2014 19:16:49] "GET /events2/ HTTP/1.1" 500 59

and

PUBLISH sse 'hola'
Traceback (most recent call last):
  File "/usr/lib/python3.3/wsgiref/handlers.py", line 138, in run
    self.finish_response()
  File "/usr/lib/python3.3/wsgiref/handlers.py", line 179, in finish_response
    for data in self.result:
  File "/opt/repositories/billing/local/lib/python3.3/site-packages/django/http/response.py", line 295, in __next__
    return self.make_bytes(next(self._iterator))
  File "../django_sse/views.py", line 26, in _iterator
    for subiterator in self.iterator():
  File "../django_sse/redisqueue.py", line 69, in iterator
    event, data = json.loads(message['data'].decode('utf-8'))
  File "/usr/lib/python3.3/json/__init__.py", line 316, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.3/json/decoder.py", line 351, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.3/json/decoder.py", line 369, in raw_decode
    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded

Max Connections

I am having an issue running the example where everything works in the first 6 open pages but from the 7th onwards they become incredibly slow. I have tried running it with gevent and multiple workers and experience the same issue.

Allow for CORS parameters

Hi, first of all thank you for your project,
it's been really easy to setup a simple SSE based view :)

I've had trouble when i needed to setup my CORS parameters, so i added headers to your "dispatch" method in the base view :

    response['Access-Control-Allow-Origin'] = '*'
    response['Access-Control-Allow-Credentials'] = 'true'

i don't know how you want to handle it,
but it's a really important feature that one can change the headers sent easily :)

Regards,

Olivier.

USE_ETAGS in settings.py breaks sse

Not sure if this is an issue with django or django-sse but definitely worth mentioning in documentation as it could save someone else alot of time.

Is there a way to support heartbeat responses?

Is there a way to support heartbeat responses? Let's say print some dummy data into streams each 30 sec to not allow browser to close connection for longer time? (IE ignores timeout value in keep-alive header). I'm thinking that expiration of heartbeat should be set in settings to support longer requests or turn that off and rely on browser completely.

I'm currently using heartbeat middleware for such purposes but maybe it can be done on django-sse level automatically and more elegant?

server_addr not set

I don't know if this is the right place. But I have problems with connecting to the SSE endpoint. Sometimes it works sometimes it doesn't. I get this error

"server": self.server_addr,
    AttributeError: 'NoneType' object has no attribute 'value'

Do you maybe know what is going on and how I can fix it?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.