Django channels Tutorial

Django Channels

Channels is a project that takes Django and extends its abilities beyond HTTP - to handle WebSockets, chat protocols, IoT protocols, and more. It’s built on a Python specification called ASGI. Channels give you the choice to handle other connections in either a synchronous or asynchronous style.

Channels gives you the tools to write these basic consumers - individual pieces that might handle chat messaging, or notifications - and tie them together with URL routing, protocol detection and other handy things to make a full application.

Projects

Channels is comprised of several packages:

  • Channels, the Django integration layer
  • Daphne, the HTTP and Websocket termination server
  • asgiref, the base ASGI library
  • channels_redis, the Redis channel layer backend (optional)

Difference between ASGI and WSGI

ASGI is the name for the asynchronous server specification that Channels is built on.

WSGI is designed to let you choose between different servers and frameworks rather than being locked into Channels.

Scopes and Events

Channels and ASGI split up incoming connections into two components: a scope, and a series of events.

Scope: The scope is a set of details about a single incoming connection. For HTTP, the scope just lasts a single request. For WebSockets, it lasts for the lifetime of the socket (but changes if the socket closes and reconnects). 

Events: During the lifetime of this scope, a series of events occur. These represent user interactions - making a HTTP request.

An example of scope and events with a chatbot:

  • The user sends the first message to the chatbot.
  • This opens a scope containing the user’s username, chosen name, and user ID. (All user details are lying under scope)
  • The application is given an chat.received_message event with the event text. It does not have to respond but could send one, two, or more other chat messages back as chat.send_message events if it wanted to. (All send and receive messages are triggering events)
  • The user sends more messages to the chatbot and more chat.received_message events are generated.

After a timeout or when the application process is restarted the scope is closed.

What is a Consumer?

A consumer is the basic unit of Channels code. We call it a consumer as it consumes events

Consumers do a couple of things in particular:

  • Structures your code as a series of functions to be called whenever an event happens, rather than making you write an event loop.
  • Allow you to write synchronous or async code and deals with handoffs and threading for you.

Of course, you are free to ignore consumers and use the other parts of Channels - like routing, session handling and authentication - with any ASGI app, but they’re generally the best way to write your application code.

 

Django Integration

Channels ships with easy drop-in support for common Django features, like sessions and authentication. You can combine authentication with your WebSocket views by just adding the right middleware around them:

from django.urls import re_path
from django.core.asgi import get_asgi_application

from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(
        URLRouter([
            re_path(r"^front(end)/$", consumers.AsyncChatConsumer.as_asgi()),
        ])
    ),
})

When Django accepts an HTTP request, it consults the root URLconf to lookup a view function, and then calls the view function to handle the request. Similarly, when Channels accepts a WebSocket connection, it consults the root routing configuration to lookup a consumer, and then calls various functions on the consumer to handle events from the connection.

 Channel layer

A channel layer is a kind of communication system. It allows multiple consumer instances to talk with each other, and with other parts of Django.

A channel layer provides the following abstractions:

  • channel is a mailbox where messages can be sent to. Each channel has a name. Anyone who has the name of a channel can send a message to the channel.
  • group is a group of related channels. A group has a name. Anyone who has the name of a group can add/remove a channel to the group by name and send a message to all channels in the group. It is not possible to enumerate what channels are in a particular group.

Every consumer instance has an automatically generated unique channel name, and so can be communicated with via a channel layer.