• Stars
    star
    1,318
  • Rank 35,685 (Top 0.8 %)
  • Language
    Python
  • License
    BSD 2-Clause "Sim...
  • Created over 13 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

WebSockets for Django
https://secure.travis-ci.org/stephenmcd/django-socketio.png?branch=master

Created by Stephen McDonald

State of django-socketio

django-socketio is currently bound to socket.io 0.6, which is considerably out of date. It's fully functional, but some browsers now have newer implementations of WebSockets, and so alternative socket.io transports are fallen back to in these cases.

Work is currently underway to bring django-socketio up to date with the latest gevent-socktio, which has just recently started to support socket.io 0.8

Follow this thread for more info:

#19

Introduction

django-socketio is a BSD licensed Django application that brings together a variety of features that allow you to use WebSockets seamlessly with any Django project.

django-socketio was inspired by Cody Soyland's introductory blog post on using Socket.IO and gevent with Django, and made possible by the work of Jeffrey Gelens' gevent-websocket and gevent-socketio packages.

The features provided by django-socketio are:

  • Installation of required packages from PyPI
  • A management command for running gevent's pywsgi server with auto-reloading capabilities
  • A channel subscription and broadcast system that extends Socket.IO allowing WebSockets and events to be partitioned into separate concerns
  • A signals-like event system that abstracts away the various stages of a Socket.IO request
  • Support for out-of-band (non-event) broadcasts
  • The required views, urlpatterns, templatetags and tests for all the above

Upgrading

Prior to version 0.3, the message argument sent to each of the event handlers was always a Python list, regardless of the data type that was used for sending data. As of 0.3, the message argument matches the data type being sent via JavaScript.

Installation

Note that if you've never installed gevent, you'll first need to install the libevent development library. You may also need the Python development library if not installed. This can be achieved on Debian based sytems with the following commands:

$ sudo apt-get install python-dev
$ sudo apt-get install libevent-dev

or on OSX using Homebrew (with Xcode installed):

$ brew install libevent
$ export CFLAGS=-I/brew/include

or on OSX using macports:

$ sudo port install libevent
$ CFLAGS="-I /opt/local/include -L /opt/local/lib" pip install django-socketio

The easiest way to install django-socketio is directly from PyPi using pip by running the following command, which will also attempt to install the dependencies mentioned above:

$ pip install -U django-socketio

Otherwise you can download django-socketio and install it directly from source:

$ python setup.py install

Once installed you can then add django_socketio to your INSTALLED_APPS and django_socketio.urls to your url conf:

urlpatterns += [
    url("", include('django_socketio.urls')),
]

The client-side JavaScripts for Socket.IO and its extensions can then be added to any page with the socketio templatetag:

<head>
    {% load socketio_tags %}
    {% socketio %}
    <script>
        var socket = new io.Socket();
        socket.connect();
        // etc
    </script>
</head>

Running

The runserver_socketio management command is provided which will run gevent's pywsgi server which is required for supporting the type of long-running request a WebSocket will use:

$ python manage.py runserver_socketio host:port

Note that the host and port can also configured by defining the following settings in your project's settings module:

  • SOCKETIO_HOST - The host to bind the server to.
  • SOCKETIO_PORT - The numeric port to bind the server to.

These settings are only used when their values are not specified as arguments to the runserver_socketio command, which always takes precedence.

Note

On UNIX-like systems, in order for the flashsocket transport fallback to work, root privileges (eg by running the above command with sudo) are required when running the server. This is due to the Flash Policy Server requiring access to a low port (843). This isn't strictly required for everything to work correctly, as the flashsocket transport is only used as one of several fallbacks when WebSockets aren't supported by the browser.

When running the runserver_socketio command in production, you'll most likely want to use some form of process manager, like Supervisor or any of the other alternatives.

Channels

The WebSocket implemented by gevent-websocket provides two methods for sending data to other clients, socket.send which sends data to the given socket instance, and socket.broadcast which sends data to all socket instances other than itself.

A common requirement for WebSocket based applications is to divide communications up into separate channels. For example a chat site may have multiple chat rooms and rather than using broadcast which would send a chat message to all chat rooms, each room would need a reference to each of the connected sockets so that send can be called on each socket when a new message arrives for that room.

django-socketio extends Socket.IO both on the client and server to provide channels that can be subscribed and broadcast to.

To subscribe to a channel client-side in JavaScript use the socket.subscribe method:

var socket = new io.Socket();
socket.connect();
socket.on('connect', function() {
    socket.subscribe('my channel');
});

Once the socket is subscribed to a channel, you can then broadcast to the channel server-side in Python using the socket.broadcast_channel method:

socket.broadcast_channel("my message")

Broadcast and Send Methods

Each server-side socket instance contains a handful of methods for sending data. As mentioned above, the first two methods are implemented by gevent-socketio:

  • socket.send(message) - Sends the given message directly to the socket.
  • socket.broadcast(message) - Sends the given message to all other sockets.

The remaning methods are implemented by django-socketio.

  • socket.broadcast_channel(message, channel=None) - Sends the given message to all other sockets that are subscribed to the given channel. If no channel is given, all channels that the socket is subscribed to are used. the socket.
  • socket.send_and_broadcast(message) - Shortcut that sends the message to all sockets, including the sender.
  • socket.send_and_broadcast_channel(message, channel=None) - Shortcut that sends the message to all sockets for the given channel, including the sender.

The following methods can be imported directly from django_socketio for broadcasting and sending out-of-band (eg: not in response to a socket event). These methods map directly to the same methods on a socket instance, and in each case an appropriate connected socket will be chosen to use for sending the message, and the django_socketio.NoSocket exception will be raised if no connected sockets exist.

  • django_socketio.broadcast(message)
  • django_socketio.broadcast_channel(message, channel)
  • django_socketio.send(session_id, message)

Note that with the send method, the socket is identified by its session ID, accessible via socket.session.session_id. This is a WebSocket session ID and should not be confused with a Django session ID which is different.

Events

The django_socketio.events module provides a handful of events that can be subscribed to, very much like connecting receiver functions to Django signals. Each of these events are raised throughout the relevant stages of a Socket.IO request. These events represent the main approach for implementing your socket handling logic when using django-socketio.

Events are subscribed to by applying each event as a decorator to your event handler functions:

from django_socketio.events import on_message

@on_message
def my_message_handler(request, socket, context, message):
    ...

Where should these event handlers live in your Django project? They can go anywhere, so long as they're imported by Django at startup time. To ensure that your event handlers are always loaded, you can put them into a module called events.py in one of your apps listed in Django's INSTALLED_APPS setting. django-socketio looks for these modules, and will always import them to ensure your event handlers are loaded.

Each event handler takes at least three arguments: the current Django request, the Socket.IO socket the event occurred for, and a context, which is simply a dictionary that can be used to persist variables across all events throughout the life-cycle of a single WebSocket connection.

  • on_connect(request, socket, context) - occurs once when the WebSocket connection is first established.
  • on_message(request, socket, context, message) - occurs every time data is sent to the WebSocket. Takes an extra message argument which contains the data sent.
  • on_subscribe(request, socket, context, channel) - occurs when a channel is subscribed to. Takes an extra channel argument which contains the channel subscribed to.
  • on_unsubscribe(request, socket, context, channel) - occurs when a channel is unsubscribed from. Takes an extra channel argument which contains the channel unsubscribed from.
  • on_error(request, socket, context, exception) - occurs when an error is raised. Takes an extra exception argument which contains the exception for the error.
  • on_disconnect(request, socket, context) - occurs once when the WebSocket disconnects.
  • on_finish(request, socket, context) - occurs once when the Socket.IO request is finished.

Like Django signals, event handlers can be defined anywhere so long as they end up being imported. Consider adding them to their own module that gets imported by your urlconf, or even adding them to your views module since they're conceptually similar to views.

Binding Events to Channels

All events other than the on_connect event can also be bound to particular channels by passing a channel argument to the event decorator. The channel argument can contain a regular expression pattern used to match again multiple channels of similar function.

For example, suppose you implemented a chat site with multiple rooms. WebSockets would be the basis for users communicating within each chat room, however you may want to use them elsewhere throughout the site for different purposes, perhaps for a real-time admin dashboard. In this case there would be two distinct WebSocket uses, with the chat rooms each requiring their own individual channels.

Suppose each chat room user subscribes to a channel client-side using the room's ID:

var socket = new io.Socket();
var roomID = 42;
socket.connect();
socket.on('connect', function() {
    socket.subscribe('room-' + roomID);
});

Then server-side the different message handlers are bound to each type of channel:

@on_message(channel="dashboard")
def my_dashboard_handler(request, socket, context, message):
    ...

@on_message(channel="^room-")
def my_chat_handler(request, socket, context, message):
    ...

Logging

The following setting can be used to configure logging:

  • SOCKETIO_MESSAGE_LOG_FORMAT - A format string used for logging each message sent via a socket. The string is formatted using interpolation with a dictionary. The dictionary contains all the keys found in Django's request["META"], as well as TIME and MESSAGE keys which contain the time of the message and the message contents respectively. Set this setting to None to disable message logging.

Chat Demo

The "hello world" of WebSocket applications is naturally the chat room. As such django-socketio comes with a demo chat application that provides examples of the different events, channel and broadcasting features available. The demo can be found in the example_project directory of the django_socketio package. Note that Django 1.3 or higher is required for the demo as it makes use of Django 1.3's staticfiles app.

More Repositories

1

mezzanine

CMS framework for Django
Python
4,757
star
2

cartridge

Ecommerce for Mezzanine
Python
708
star
3

django-forms-builder

Let users build forms in Django admin
Python
689
star
4

curiodb

Distributed NoSQL Database
Scala
511
star
5

drum

Reddit / Hacker News clone for Mezzanine
Python
387
star
6

hot-redis

Rich Python data types for Redis
Python
290
star
7

gnotty

IRC web client and bot framework
Python
159
star
8

django-overextends

Circular template inheritance for Django
Python
108
star
9

two-queues

Benchmarking Redis and ZeroMQ pub-sub, using Python and Go
Go
105
star
10

gunicorn-console

A curses application for managing gunicorn processes.
Python
90
star
11

django-postgres-fuzzycount

Fast / fuzzy PostgreSQL counts for Django
Python
89
star
12

django-email-extras

PGP encrypted / multipart templated emails for Django
Python
75
star
13

filebrowser-safe

File manager for Mezzanine
Python
41
star
14

hg-github

A Mercurial extension for working with GitHub repositories.
Python
40
star
15

vimeo-deck

Synchronize Speaker Deck presentations with Vimeo videos.
JavaScript
28
star
16

gamblor

An online casino app built for Django Dash 2012
JavaScript
26
star
17

grappelli-safe

Admin skin for Mezzanine
CSS
25
star
18

snazzymaps-browser

Android app for searching and browsing Snazzy Maps
Java
24
star
19

grillode

A web-based chat application written in CoffeeScript for Node.js
CoffeeScript
23
star
20

drawnby

Drawn By is a collaborative real-time sketching app built for the 2011 Django Dash.
JavaScript
23
star
21

babbler

A Twitter bot that polls an RSS feed and posts its entries as tweets, with auto-generated hashtags.
Python
21
star
22

tastypie-msgpack

MsgPack support for Django Tastypie.
Python
21
star
23

django-shotgun

Test entire Django sites
Python
17
star
24

linkedout

Build PDF resumes with the LinkedIn API
Ruby
15
star
25

sphinx-me

Wraps your README-only projects in a dynamic Sphinx shell for hosting on http://readthedocs.org
Python
12
star
26

readertray

Cross platform desktop notifications for RSS
Python
9
star
27

indexed-tree-map

JDK's enhanced red-black tree map algorithm to support access by index
Java
9
star
28

otr

Combined GitHub and Bitbucket API.
Ruby
8
star
29

aspchat

Classic ASP chat application
ASP
8
star
30

bitbucket-batch

A tool for bulk updating access to bitbucket.org repos.
Python
8
star
31

grillo

A terminal based chat server and client.
Python
7
star
32

mezzanine.jupo.org

Mezzanine/Cartridge project and demo site
Python
6
star
33

ratemyflight

A web app built for the Django Dash hackathon 2010.
JavaScript
6
star
34

klout-feed

Receive your daily Klout score via RSS.
Ruby
6
star
35

slbuddy

Tool for tracking sales data in Secondlife.com
Python
3
star
36

virtualboxing

Utilities for comparing timings on bulk operations across databases in a distributed environment.
Ruby
3
star
37

cryptopals

Matasano Crypto Challenges
Go
3
star
38

ghetto-life-stream

Parses items for a Google Buzz feed from various sources.
PHP
2
star
39

teamcity-client

Team City HTTP client.
Ruby
2
star
40

sydjango-damm

Code for my SyDjango talk "Django Admin: The Missing Manual"
Python
2
star
41

jquery-squeezebox

Replacement for jquery.ui.accordion to avoid dealing with jquery.ui theming.
JavaScript
2
star
42

lime

JavaScript framework, predates jQuery
JavaScript
1
star
43

cmdsvr

Toy web application server
Python
1
star
44

gedit-ftp-browser

FTP plugin for Gedit
Python
1
star