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.