Warning
This documentation is out of date and the project is not maintained or supported, it very likely doesn't work at all and you'll probably be more lucky having a look at something else (I recommend websocket server not tied to Django).
Notice
Beware! This project is highly experimental. It is my personal project which may result in lack of documentation, lack of my attention due to busy time etc.
Due to its early stage, it's API is subject to change (not drastically, but still).
Please feel free to create an issue if you feel that something should be improved regarding code or documentation. I also encourage you to hack the source code, it is pretty short and can provide better understanding of what's going on.
Installation
Requirements
- gevent-socketio from my gevent-socketio repository
(commit
8835a91dffba4447564ffa30df95663a13e1997e
) and its dependencies - pip
- django >= 1.3
- git ;)
In Red Hat/CentOS/Fedora they can be obtained by following commands:
sudo yum install libevent-devel python-devel python-setuptools gcc git-core sudo easy_install pip
In Debian/Ubuntu:
sudo apt-get install libevent-dev python-dev python-setuptools gcc git-core sudo easy_install pip
You also want to have Socket.IO client, such client in version 0.9.6 is provided by this project.
To install dependencies to use chat example please execute:
pip install -r requiements.txt
Installation itself
Django-realtime is distributed as setuptools package. To install it with pip execute:
pip install git+https://[email protected]/jstasiak/django-realtime.git
Introduction
This application allow you to use Socket.IO based communication within your Django project. It uses fairly recent version of Socket.IO - currently 0.9.6. What I like in Socket.IO newer than 0.6 is that it has additional communication channels - events. Every event can be acknowledged with optional return data which is really nice feature.
It also uses gevent-socketio development version patched by me. Without gevent-socketio this application wouldn't exist.
Some features of django-realtime are inspired by django-socketio project (https://github.com/stephenmcd/django-socketio). I like django-socketio, but:
- it provides channels (pretty much something like Socket.IO events) by modifying client code, I wanted to avoid that
- supports only Socket.IO 0.6, so there is no events and no akcnowledgements (as far as I know)
- has its own event system. django-realtime had such custom system in the past, but I have decided to rewrite it to use Django signals and I am happy with that, also it is interface which people are familiar with
- I started this project before I discovered django-socketio ;)
Django-realtime Python package name is simply realtime
.
Configuration of your project
Backend
Next step is to configure Django project to use realtime
app. To achieve this, you have to:
add
realtime
application to DjangoINSTALLED_APPS
setting, for example:INSTALLED_APPS += ['realtime']
configure URL dispatcher - you have to put this code in your main
urls.py
file:urlpatterns += patterns('', url(r'^socket.io/', include('realtime.urls')) )
Frontend
If you want to use Socket.IO client provided by django-realtime, put following code in HEAD
section of your HTML template file:
{% load socketio %} {% socketio_client_script %}
Socket.IO client provided by this project is not modified and is provided purely for your convenience.
Then you probably would write some code actually connecting to server and making use of Socket.IO client. This is beyond this projects scope, although I present here template I always take and customize:
socket = io.connect(null, { transports: ['flashsocket', 'xhr-polling'] }); socket.on('connect', function() { console.log('connected'); }); socket.on('disconnect', function() { console.log('disconnected'); }); socket.on('reconnecting', function() { console.log('reconnecting'); }); socket.on('reconnect', function() { console.log('reconnected'); }); socket.on('error', function(e) { console.log('error: ' + e); }); socket.on('message', function(message) { console.log('received:'); console.dir(message); });
Warning! In current development version (it is still correct at 2011-11-16) of gevent-socketio websocket transport is not working, so to avoid errors please restrict client transport list so that websocket is not there (like in the example above).
Running server
Due to high number of possible concurrent and long running connections you cannot use traditional server like Apache + mod_wsgi to host project using django-realtime. I use gevents pywsgi server.
You can run this server by executing the following command within your project root directory:
python manage.py rungevent [interface:port]
Interface and port part is optional, it defaults to localhost and 8000.
If you want to be able to connect to the server from remote hosts, enter 0
as interface, like
this:
python manage.py rungevent 0:8000
API
Current connections
In the top-level of realtime package there is connected_sockets
sequence which contains,
what a surprise, currently connected sockets. These sockets are gevent-socketio SocketIOProtocol instances.
Usage
You can for example iterate over it and list connected session ids:
from realtime import connected_sockets print('Connected sockets:') for socket in connected_sockets: print('- {0}'.format(socket.session.session_id))
When you have reference to connected socket
(obtained from realtime.connected_sockets
,
from signal handler parameter sender
or by other means), you can use following methods:
# sends string 'Hallelujah!' by this particular socket to this particular client # signature: socket.send(STRING) socket.send('Hallelujah!') # emits event named 'notice' with arguments 1, 2 and '!!!' # signature: socket.emit(EVENT_NAME, *args) socket.emit('notice', 1, 2, '!!!') # these are just like socket.send and socket.emit, but send message/event to all # clients but this one socket.broadcast_send('Hey! New user connected!') socket.broadcast_emit('notice', 'Server is shutting down', 'kaboom')
In current implementation of gevent-socketio
, if message passed to socket.send
is not
basestring instance, it will be converted to its string representation. There is no JSON
encoding here.
On the other hand, arguments supplied to socket.emit
, broadcast_emit
and socket.ack
are
JSON encoded.
Events
Handling input from sockets is based on Django signals.
In module realtime.signals
we have:
socket_connected
- when client connectssocket_disconnected
- when client disconnectssocket_client_message
- when you dosocket.send('some data')
in the clientsocket_client_event
- fires when you dosocket.emi('event_name', ...)
in the clientsocket_client_event_by_type
- dictionary which is indexed by client event name and returns associated signal
In module realtime.events
there is Event
class defined. Its public interface visible for listeners is as follows:
ack(*params)
- functions which confirms receiving event and can be passed some data to send to client in confirmationdata
- event dataname
- name of the eventacknowledgeable()
- true if this event can be acknowledgedacknowledged()
- true if this event has been acknowledged already
Usage
from django.dispatch import receiver from realtime.signals import socket_connected, socket_disconnected, socket_client_message, socket_client_event @receiver(socket_connected) def handle_connected(sender, request, **kwargs): socket = sender print('{0} connected'.format(socket.session.session_id)) @receiver(socket_disconnected) def handle_disconnected(sender, request, **kwargs): socket = sender print('{0} disconnected'.format(socket.session.session_id)) @receiver(socket_client_message) def handle_message(sender, request, message, **kwargs): socket = sender print('{0} => message {1!r}'.format(socket.session.session_id, message)) @receiver(socket_client_event) def handle_event(sender, request, event, **kwargs): socket = sender print('{0} => event {1!r} ({2!r})'.format(socket.session.session_id, event.name, event.data)) if event.acknowledgeable: event.ack('I have received your message!')
Example
In project root you can find example_chat
directory. It contains very simple live chat
implementation which uses django-realtime.
I warn you, it is just proof of concept and do not expect it to work flawlessly.
License
This project code is licensed under BSD license unless stated otherwise. Take it and use it.
This repository also contains Socket.IO
client which has its own license.