Real-Time with Django Channels
Django Channels is an official extension that adds WebSockets and other long-lived connections to Django over the ASGI layer, so the server can push data to the browser in real time instead of only answering one request at a time.
Learn Real-Time with Django Channels in our free Django course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…
Part of the free Django course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll write a WebSocket consumer with its connect, receive, and disconnect handlers, understand the channel layer backed by Redis, and broadcast to groups so one message reaches every socket in a room.
A consumer is to a WebSocket what a view is to an HTTP request — except the connection stays open. You subclass AsyncWebsocketConsumer and implement three lifecycle handlers: connect when the socket opens, receive each time a message arrives, and disconnect when it closes. The consumer accepts the connection, reacts to messages, and cleans up.
One open socket talking to itself isn't useful. The channel layer is a shared message bus that lets consumers — even across different worker processes — reach each other through named groups . A consumer joins a group with group_add and leaves with group_discard . Because workers are spread across processes, the layer needs a backend they all share, which in production is Redis .
To send a chat message to everyone in a room, the consumer calls group_send with an event whose type names a handler method. The layer then invokes that method — chat_message here — on every consumer in the group, and each one sends the text down its own socket. Finally, you route WebSocket URLs in the ASGI application, the WebSocket equivalent of urls.py .
Replace the blank with the group name "lobby" so both members receive the broadcast.
❌ The WebSocket connects then immediately closes
✅ Fix: call await self.accept() at the end of connect .
No channel layer is configured, or consumers never joined a group.
✅ Fix: set CHANNEL_LAYERS to Redis and call group_add in connect .
The event type doesn't match a method on the consumer.
✅ Fix: define a method named after the type (e.g. chat_message for type "chat_message" ).
Build a tiny channel layer with multiple rooms. A message published to the sports room must reach only its subscribers, never the music room.
Lesson complete — your app can talk in real time!
You wrote a WebSocket consumer with connect, receive, and disconnect, configured the Redis-backed channel layer, joined and left groups, and broadcast a message to every socket in a room with group_send.
🚀 Up next: Background Tasks with Celery — push slow work off the request and run it in the background.
Practice quiz
What does Django Channels add to Django?
- A faster ORM
- Support for WebSockets and long-lived connections
- Automatic migrations
- A new admin theme
Answer: Support for WebSockets and long-lived connections. Channels adds WebSockets and other long-lived connections over the ASGI layer.
What is a consumer in Channels?
- A database model
- A URL pattern
- The equivalent of a view for a persistent connection
- A cache backend
Answer: The equivalent of a view for a persistent connection. A consumer handles a connection's lifecycle: connect, receive, and disconnect.
Which handler runs each time a WebSocket message arrives?
- connect
- disconnect
- accept
- receive
Answer: receive. receive runs every time a message arrives on the open socket.
What must connect() call so the WebSocket handshake succeeds?
- self.accept()
- self.open()
- self.start()
- self.connect()
Answer: self.accept(). Without self.accept() (or self.close()), the browser's handshake fails.
What is the channel layer?
- A template engine
- A shared message bus that lets consumers reach each other
- A migration tool
- A static file server
Answer: A shared message bus that lets consumers reach each other. The channel layer is a shared bus letting consumers across processes communicate.
Which backend is standard for the channel layer in production?
- SQLite
- Memcached
- Redis (via channels_redis)
- PostgreSQL
Answer: Redis (via channels_redis). channels_redis backs the channel layer with Redis so all workers share groups.
Which methods join and leave a group?
- join / leave
- subscribe / unsubscribe
- open / close
- group_add / group_discard
Answer: group_add / group_discard. A consumer joins with group_add and leaves with group_discard.
How do you broadcast an event to every consumer in a group?
- channel_layer.group_send(group, event)
- channel_layer.broadcast(event)
- self.send_all(event)
- group.publish(event)
Answer: channel_layer.group_send(group, event). group_send delivers the event to a matching handler on every group member.
In a group event, what does the 'type' key determine?
- The Redis host
- The group name
- The handler method name invoked on each consumer
- The close code
Answer: The handler method name invoked on each consumer. The event's type names the handler method, e.g. type 'chat_message' calls chat_message.
What is a group in Channels?
- A Django permission set
- A named set of channels
- A database table
- An HTTP middleware
Answer: A named set of channels. A group is a named set of channels, like all sockets in one chat room.