WebSocket Options in Django
While Django doesn’t come out of the box with Web Socket support, today we have very good options for using WebSockets with Django. In the past, there were many attempts to glue WebSockets into Django and some even worked well. But today they are not maintained or are not the ideal implementation.
It can be hard to know which of these options is the best to use so in this post I’ll present you with the two best options for WebSockets I see today in Django.
The Blessed One: Django Channels
Django Channels is as close to you’re going to get to official WebSocket support in Django. It was started by Andrew Godwin, who gave us great things like database migrations in core Django. It may eventually make its way into core Django, but for right now, it’s an external library that integrates well with Django.
Django Channels gives you an abstraction layer that helps you implement WebSockets, HTTP2, background tasks and more. It also comes with other features like Groups and Data Binding that will help you accomplish some really complex tasks with Django pretty easily.
So if Django Channels is so awesome, why use anything else? The cost of all these advanced features is a more complex system with multiple layers to deploy and maintain. To support all these features you need an ASGI server, Django workers, and something to route ASGI requests like Redis. This is most likely in addition to normal Django web workers to handle normal everyday HTTP requests. If you have an application that needs some of Django Channels features, then the complexity is warranted; however, if you just need a WebSocket to do a simple task for you and you’re not building the next Slack, then a smaller solution is better.
MacGyvering WebSockets: Tornado
Another great web framework for Python is Tornado and it comes with WebSockets built-in. It gives you a lower-level implementation but is very easy to use and great for implementing simpler use cases.
Wouldn’t it be great if we could tack on some Tornado in our Django and use both? You could do this by running two different workers, one for Tornado and one for Django. But we can do even better. Tornado has a fallback handler, which lets you create a Tornado app that can handle our WebSockets but otherwise fall back to Django. It sounds pretty hackish, but it actually works really well.
Here’s a template to get you started with your Tornado + Django integration.
This code comes from a project where I did a Progressive Web App. Since PWAs cache themselves offline, I needed a way to send a new release signal so the app updates appropriately. I accomplished this with a WebSocket that pushes a message out when data in the app has changed.
This piece of code replaces your runserver command like Gunicorn or µWsgi. To run your Django app, you now run python run_tornado.py. Tornado will intercept any requests that match your WebSocket URL or otherwise pass it to your Django app. It’s a really simple and elegant way to tack on real-time goodness to Django without much work and extra overhead.
Originally published at www.digitalcrafts.com on November 14, 2017.