Today, we're thrilled to host Jacob Kaplan-Moss. Jacob's a former Herokai and long-time core contributor to Django, and he's here to share an in-depth look at something that he believes will define the future of the framework.
When Django was created, over ten years ago, the web was a less complicated place. The majority of web pages were static. Database-backed, Model/View/Controller-style web apps were the new spiffy thing. Ajax was barely starting to be used, and only in narrow contexts.
The web circa 2016 is significantly more powerful. The last few years have seen the rise of the so-called “real-time” web: apps with much higher interaction between clients and servers and peer-to-peer. Apps comprised of many services (a.k.a. microservices) are the norm. And, new web technologies allow web apps to go in directions we could only dream of a decade ago. One of these core technologies are WebSockets: a new protocol that provides full-duplex communication — a persistent, open connection between the client and the server, with either able to send data at any time.
In this new world, Django shows its age. At its core, Django is built around the simple concept of requests and responses: the browser makes a request, Django calls a view, which returns a response that’s sent back to the browser:
This doesn’t work with WebSockets! The view is only around for the lifespan of a single request, and there’s no mechanism to hold open a connection or send data down to the client without an associated request.
Thus: Django Channels. Channels, in a nutshell, replaces the “guts” of Django — the request/response cycle — with messages that are sent across channels. Channels allows Django to support WebSockets in a way that’s very similar to traditional HTTP views. Channels also allow for background tasks that run on the same servers as the rest of Django. HTTP requests continue to behave the same as before, but also get routed over channels. Thus, under Channels Django now looks like this:
As you can see, Channels introduces some new concepts to Django:
Channels are essentially task queues: messages get pushed onto the channel by producers, and then given to one of the consumers listening on that channel. If you’ve used channels in Go, the concept should be fairly familiar. The main difference is that Django channels work across a network and allow producers and consumers to run transparently across many dynos and/or machines. This network layer is called the channel layer. Channels is designed to use Redis as its preferred channel layer, though there is support for other types (and a first-class API for creating custom channel layers). There are neat and subtle technical details; consult the documentation for the full story.
Right now, Channels is available as a stand-alone app that works with Django 1.9. The plan is to roll Channels into Django for the 1.10 release, due out some time this summer.
I believe that Channels will be an incredible important addition to Django: they allow Django to move smoothly into this new age of web development. Although these APIs aren’t part of Django yet, they will be soon! So, now’s a perfect time to start learning about Channels: you can learn about the future of Django before it lands.
Getting started: how to make a real-time chat app in Django
As an example, I’ve built a simple real-time chat app — like a very, very light-weight Slack. There are a bunch of rooms, and everyone in the same room can chat, in real-time, with each other (using WebSockets).
You can visit my deployment of the example online, check out the code on GitHub, or deploy your own copy with this button (which requires a free Heroku account, so sign up for that first):
Note: you'll need to scale the worker process type up after using the button. Use the Dashboard, or run heroku ps:scale web=1:free worker=1:free.
For in-depth details on how the app works — including why you need worker dynos! — read on. I’ll walk through the steps to take to build this app, and highlight the import bits and concepts along the way.
First steps — it’s still Django
Although there are differences under the hood, this is still the same Django we’ve been using for ten years. So the initial steps are the same as any Django app. (If you’re new to Django, you might want to check out Getting Started With Python on Heroku and/or the Django Girls Tutorial.) After creating a project, we can define model to represent a chat room, and the messages within it (chat/models.py):
(In this, and all subsequent examples, I’ve trimmed the code down to the bare minimum, so we can focus on the important bits. For the full messy detailed code, see the project on Github.)
And then a view (chat/views.py, and the associated urls.py and chat/room.html template):
At this point, we have a functioning — if unexciting — Django app. If you run this with a standard Django install, you’d be able to see existing chat rooms and transcripts, but not interact with them in any way. Real-time chat doesn’t work — for that we need something that can handle WebSockets.