{"id":1959,"library":"channels","title":"Channels","description":"Channels is a project that extends Django's capabilities beyond traditional HTTP, enabling it to handle asynchronous protocols such as WebSockets, chat protocols, and IoT protocols. It is built upon the Asynchronous Server Gateway Interface (ASGI) specification, allowing Django applications to support long-running, event-driven connections alongside conventional HTTP views. The library is currently at version 4.3.2 and is actively maintained as an official Django Project, aligning its release cadence and Python/Django version support with the core framework.","status":"active","version":"4.3.2","language":"en","source_language":"en","source_url":"http://github.com/django/channels","tags":["django","async","websockets","asgi","real-time","chat"],"install":[{"cmd":"pip install channels","lang":"bash","label":"Base Installation"},{"cmd":"pip install 'channels[daphne]' channels_redis","lang":"bash","label":"Recommended for Production (with Daphne & Redis)"}],"dependencies":[{"reason":"Core framework extension.","package":"Django"},{"reason":"Base ASGI library, core dependency for async utilities.","package":"asgiref","optional":false},{"reason":"HTTP and WebSocket termination server (recommended for production deployment).","package":"daphne","optional":true},{"reason":"Redis-backed channel layer for inter-process communication (recommended for production/distributed setups).","package":"channels-redis","optional":true}],"imports":[{"note":"Used in asgi.py to route different protocol types (http, websocket).","symbol":"ProtocolTypeRouter","correct":"from channels.routing import ProtocolTypeRouter"},{"note":"Used within ProtocolTypeRouter to route WebSocket paths to specific consumers.","symbol":"URLRouter","correct":"from channels.routing import URLRouter"},{"note":"Wraps WebSocket consumers to enable Django's authentication and session features.","symbol":"AuthMiddlewareStack","correct":"from channels.auth import AuthMiddlewareStack"},{"note":"Base class for synchronous WebSocket consumers.","symbol":"WebsocketConsumer","correct":"from channels.generic.websocket import WebsocketConsumer"},{"note":"Base class for asynchronous WebSocket consumers.","symbol":"AsyncWebsocketConsumer","correct":"from channels.generic.websocket import AsyncWebsocketConsumer"},{"note":"Helper to call synchronous code from asynchronous contexts (e.g., database access in async consumers).","symbol":"sync_to_async","correct":"from asgiref.sync import sync_to_async"},{"note":"Helper to call asynchronous code from synchronous contexts (less common in consumers).","symbol":"async_to_sync","correct":"from asgiref.sync import async_to_sync"},{"note":"The standard way to integrate Django's HTTP handling into an ASGI application (supersedes channels.http.AsgiHandler).","symbol":"get_asgi_application","correct":"from django.core.asgi import get_asgi_application"}],"quickstart":{"code":"import os\nfrom channels.auth import AuthMiddlewareStack\nfrom channels.routing import ProtocolTypeRouter, URLRouter\nfrom channels.security.websocket import AllowedHostsOriginValidator\nfrom django.core.asgi import get_asgi_application\nfrom django.urls import path\n\nos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')\n\n# Initialize Django ASGI application early to ensure the AppRegistry\n# is populated before importing code that may import ORM models.\ndjango_asgi_app = get_asgi_application()\n\n# myapp/consumers.py (example consumer)\n# from channels.generic.websocket import AsyncWebsocketConsumer\n# import json\n# class ChatConsumer(AsyncWebsocketConsumer):\n#     async def connect(self):\n#         self.room_name = self.scope['url_route']['kwargs']['room_name']\n#         self.room_group_name = 'chat_%s' % self.room_name\n#         await self.channel_layer.group_add(\n#             self.room_group_name,\n#             self.channel_name\n#         )\n#         await self.accept()\n#\n#     async def disconnect(self, close_code):\n#         await self.channel_layer.group_discard(\n#             self.room_group_name,\n#             self.channel_name\n#         )\n#\n#     async def receive(self, text_data):\n#         text_data_json = json.loads(text_data)\n#         message = text_data_json['message']\n#         await self.channel_layer.group_send(\n#             self.room_group_name,\n#             {\n#                 'type': 'chat_message',\n#                 'message': message\n#             }\n#         )\n#\n#     async def chat_message(self, event):\n#         message = event['message']\n#         await self.send(text_data=json.dumps({'message': message}))\n\n# myproject/routing.py\n# from django.urls import re_path\n# from myapp import consumers\n#\n# websocket_urlpatterns = [\n#     re_path(r'ws/chat/(?P<room_name>\\w+)/$', consumers.ChatConsumer.as_asgi()),\n# ]\n\n# Root ASGI application in myproject/asgi.py\napplication = ProtocolTypeRouter({\n    \"http\": django_asgi_app,\n    \"websocket\": AllowedHostsOriginValidator(\n        AuthMiddlewareStack(\n            URLRouter(\n                # myproject.routing.websocket_urlpatterns  # Uncomment and define your routing\n                [\n                    path(\"ws/echo/\", (lambda scope: type('EchoConsumer', (object,), {'as_asgi': lambda: lambda scope, receive, send: (async def _(): await scope['accept'](), await scope['send']({'type': 'websocket.accept'}), async for msg in scope['receive'](): await scope['send']({'type': 'websocket.send', 'text': msg['text']})})())())(0).as_asgi())\n                ]\n            )\n        )\n    ),\n})","lang":"python","description":"This quickstart demonstrates a minimal `asgi.py` configuration using `ProtocolTypeRouter` to handle both HTTP (via Django's `get_asgi_application()`) and WebSocket connections. It includes `AuthMiddlewareStack` for session and authentication support and `AllowedHostsOriginValidator` for security. The example uses an inline echo consumer for immediate testing, but typically you would define consumers in an app's `consumers.py` and route them via a `routing.py` module. To run this, you would also need `daphne` installed and configured in `INSTALLED_APPS`."},"warnings":[{"fix":"Refer to the Channels 2.x migration guide for porting applications. Expect to rewrite consumer and middleware logic to use async/await and new API patterns. Update Python to 3.5+.","message":"Channels 1.x to 2.x was a complete rewrite, introducing Python's asyncio framework and running async-native. It is not backwards-compatible, requiring significant code changes and dropping Python 2.7/3.4 support. The `channel_session` concept was removed, and applications now run inside their protocol servers.","severity":"breaking","affected_versions":"<2.0.0"},{"fix":"Ensure consumers are called with `.as_asgi()` in your routing. Update custom middleware to the new ASGI v3 signature. Replace `AsgiHandler` with `django.core.asgi.get_asgi_application` for HTTP handling.","message":"Channels 3.x introduced ASGI v3 compliance, aligning with Django's native ASGI support (Django 3.0+). Consumers now require an `.as_asgi()` class method when used in routing. Middleware signatures changed, and `channels.http.AsgiHandler` was deprecated in favor of Django's `get_asgi_application()`.","severity":"breaking","affected_versions":"<3.0.0"},{"fix":"Explicitly install `daphne` if you intend to use it. Update your `asgi.py` to use `django.core.asgi.get_asgi_application()` for HTTP. Ensure your Python and Django versions meet the new minimum requirements.","message":"Channels 4.x made Daphne an optional dependency. It also removed deprecated static files handling and the `AsgiHandler`. The minimum supported Django version is 3.2, and Python 3.7. (As of 4.3.2, Python >=3.9 and Django 4.2+ are supported).","severity":"breaking","affected_versions":"<4.0.0"},{"fix":"Use `asgiref.sync.sync_to_async` to wrap synchronous database calls or any blocking synchronous code when called from an asynchronous consumer (e.g., `await sync_to_async(MyModel.objects.get)(id=some_id)`).","message":"Mixing synchronous Django ORM operations with asynchronous Channels consumers can lead to blocking issues if not handled correctly. Django's database access is synchronous.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Configure a production-ready channel layer like `channels_redis` in your `settings.py` (e.g., `CHANNEL_LAYERS = {'default': {'BACKEND': 'channels_redis.core.RedisChannelLayer', 'CONFIG': {'hosts': [('localhost', 6379)]}}}`). Ensure Redis is running and accessible.","message":"For distributed applications, real-time communication between multiple consumer instances, or persisting messages across processes (e.g., chat rooms), a channel layer backend (like `channels_redis`) is crucial. The default `InMemoryChannelLayer` is only suitable for single-process development and will not work across multiple servers or even multiple worker processes.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Place `os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')` and `django_asgi_app = get_asgi_application()` at the top of your `asgi.py` before any imports from Django apps or Channels routing that might touch Django models.","message":"It's critical to initialize Django's ASGI application early in your `asgi.py` file (`django_asgi_app = get_asgi_application()`) to ensure the Django AppRegistry is fully populated before any ORM models or app-specific code is imported within your Channels routing or consumers.","severity":"gotcha","affected_versions":"All versions (especially with Django 3.0+)"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}