Not Logged In

django-gevent-websocket 0.1.0

Introduction

WSGI is thought to be largely incompatible with WebSockets, but that’s not necessarily the case. As is shown by gevent-websocket, you can get a really easy WSGI/WebSocket server running using gunicorn.

However, it would be really nice to be able to integrate a WebSocket server with Django. That is, not just have access to the Django models, but access to the whole Django infrastructure. Whilst it may not make much sense to use the template rendering, it certainly would be convenient to get access to the middleware and authentication from your django project. And being able to use the django form handling to validate user input means you can write more robust code.

This module allows you to do just that. You run a server alongside your normal WSGI server, that listens for WebSocket connection requests. An incoming connection is handled initially by the Django url routing facility (but with a seperate urlconf), and the Django middleware is applied. Then, your WebSocket view function is called, that handles the connection from that point on.

Warning

This is still a work in progress. I’m not using it in any projects other than for testing. It may actually turn out not to be feasible to use this for production-level WebSockets, but I am still hopeful.

If you want to use {% websocket_url %} to get absolute urls that point to the correct WebSocket server and port, then you’ll need to set

Views

A WebSocket view function looks very much like a normal django view function, indeed, it is called by the regular django request cycle, but it does not return an HttpResponse object. Instead, you grab the websocket object from the request, and .receive() data from it, or .send(data) to it.

This decorator adds the websocket as the second argument to your view: you still have the request object, allowing you to do things like permissions checking. You can still use any of the regular django decorators if you wish.

Asynchronicity in views

A WebSocket view should listen for incoming data from the client that needs to be processed, but will probably also want to be listening for data coming from another source, that will be sent back to the client.

A simple way to do this is to use the select.select function, and use this to write non-blocking code that waits for a signal to proceed. Typically, you’ll want to loop until the websocket is closed, and then wait for a signal:

Note this runs on a different port than your django development server (or gunicorn in production). In production you will probably stick both of them behind an nginx proxy or similar. If you want to do this, you may have to do some tricky to get the splitting out of the websocket connections to work. I did something like: