### Install Selenium Source: https://github.com/django/channels/blob/main/docs/tutorial/part_4.md Install the Selenium library using pip to enable browser automation for testing. ```sh $ python3 -m pip install selenium ``` -------------------------------- ### Install Channels with Daphne Source: https://github.com/django/channels/blob/main/docs/installation.md Use this command to install Channels along with the Daphne ASGI application server. For other servers, install 'channels' without the optional add-on. ```sh python -m pip install -U 'channels[daphne]' ``` -------------------------------- ### Install Nginx and Supervisor Source: https://github.com/django/channels/blob/main/docs/deploying.md Install necessary packages for serving web traffic with Nginx and managing processes with Supervisor on Ubuntu. ```sh $ sudo apt install nginx supervisor ``` -------------------------------- ### Install Channels with Type Support Source: https://github.com/django/channels/blob/main/docs/installation.md Alternatively, install Channels with the 'types' extra to include type support directly. ```sh python -m pip install 'channels[types]' ``` -------------------------------- ### Install Dependencies and Run Tests Source: https://github.com/django/channels/blob/main/CONTRIBUTING.rst Install the project dependencies, including testing tools, and run the test suite to ensure your changes do not break existing functionality. Use 'noglob' if using zsh. ```sh python -m pip install -e .[tests,daphne] ``` ```sh pytest ``` ```sh noglob python -m pip install -e .[tests] ``` -------------------------------- ### ASGI Application Example Source: https://github.com/django/channels/blob/main/docs/topics/routing.md Example of an asgi.py file demonstrating the use of ProtocolTypeRouter to handle HTTP and WebSocket connections, including authentication and URL routing for WebSockets. ```APIDOC ## ASGI Application Example ### Description This example shows a typical `asgi.py` file setup for a Channels project, using `ProtocolTypeRouter` to direct traffic based on protocol. It handles traditional HTTP requests via Django's ASGI application and WebSocket connections through a custom routing setup. ### Method N/A (Configuration file) ### Endpoint N/A (Configuration file) ### Parameters N/A ### Request Example N/A ### Response N/A ```python import os from channels.auth import AuthMiddlewareStack from channels.routing import ProtocolTypeRouter, URLRouter from channels.security.websocket import AllowedHostsOriginValidator from django.core.asgi import get_asgi_application from django.urls import path os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") # Initialize Django ASGI application early to ensure the AppRegistry # is populated before importing code that may import ORM models. django_asgi_app = get_asgi_application() from chat.consumers import AdminChatConsumer, PublicChatConsumer application = ProtocolTypeRouter({ # Django's ASGI application to handle traditional HTTP requests "http": django_asgi_app, # WebSocket chat handler "websocket": AllowedHostsOriginValidator( AuthMiddlewareStack( URLRouter([ path("chat/admin/", AdminChatConsumer.as_asgi()), path("chat/", PublicChatConsumer.as_asgi()), ]) ) ), }) ``` ``` -------------------------------- ### Install Channels Redis Backend Source: https://github.com/django/channels/blob/main/docs/deploying.md Installs the necessary package for using Redis as a channel backend. ```sh pip install -U channels_redis ``` -------------------------------- ### Install Latest Development Version Source: https://github.com/django/channels/blob/main/docs/installation.md Clone the Channels repository and install it in editable mode using pip to use the latest development version. ```sh $ git clone git@github.com:django/channels.git $ cd channels $ (environment) $ pip install -e . # the dot specifies the current repo ``` -------------------------------- ### Install Channels in Editable Mode with Test Dependencies Source: https://github.com/django/channels/blob/main/docs/contributing.md Install the Channels project in editable mode and include the necessary testing dependencies. This command should be run after navigating into the cloned 'channels' directory. ```sh python -m pip install -e .[tests] ``` -------------------------------- ### Install Channels with Daphne Source: https://github.com/django/channels/blob/main/CHANGELOG.txt Use this command to install Channels along with the Daphne ASGI server. Ensure to update channels and channels-redis as appropriate. ```bash pip install -U 'channels[daphne]' channels-redis ``` -------------------------------- ### Install Channels Type Stubs Source: https://github.com/django/channels/blob/main/docs/installation.md Install the type stubs for Channels to enable type checking support in your project. ```sh python -m pip install types-channels ``` -------------------------------- ### Install pytest for Async Tests Source: https://github.com/django/channels/blob/main/docs/topics/testing.md Install pytest-django and pytest-asyncio to enable async testing with pytest. ```sh python -m pip install -U pytest-django pytest-asyncio ``` -------------------------------- ### Install channels_redis Source: https://github.com/django/channels/blob/main/docs/tutorial/part_2.md Installs the channels_redis package, which provides the interface for Channels to use Redis as a channel layer. ```sh $ python3 -m pip install channels_redis ``` -------------------------------- ### Start Django Channels Development Server Source: https://github.com/django/channels/blob/main/docs/tutorial/part_3.md Run the Django development server with Channels support. Ensure your Django project is configured to use Channels. ```sh $ python3 manage.py runserver ``` -------------------------------- ### Run Daphne Protocol Server Source: https://github.com/django/channels/blob/main/docs/deploying.md Starts the Daphne protocol server to run the ASGI application. The application object from `myproject.asgi` is specified. ```sh daphne -p 8001 myproject.asgi:application ``` -------------------------------- ### Check Channels and Daphne Versions Source: https://github.com/django/channels/blob/main/docs/tutorial/part_1.md Confirm that Channels and Daphne are installed by checking their versions using this Python command. ```python python3 -c 'import channels; import daphne; print(channels.__version__, daphne.__version__)' ``` -------------------------------- ### Run Django Development Server with Daphne Source: https://github.com/django/channels/blob/main/docs/tutorial/part_1.md Execute this command to start the Django development server using Daphne as the ASGI interface. Observe the output to confirm Daphne is active. ```sh $ python3 manage.py runserver ``` -------------------------------- ### Check Django Version Source: https://github.com/django/channels/blob/main/docs/tutorial/part_1.md Verify that Django is installed and check its version by running this command in your shell. ```sh $ python3 -m django --version ``` -------------------------------- ### AsyncWebsocketConsumer Example Source: https://github.com/django/channels/blob/main/docs/topics/consumers.md An asynchronous version of WebsocketConsumer for handling WebSocket connections. All methods must be defined as async. It also manages group membership automatically. ```python from channels.generic.websocket import AsyncWebsocketConsumer class MyConsumer(AsyncWebsocketConsumer): groups = ["broadcast"] async def connect(self): # Called on connection. # To accept the connection call: await self.accept() # Or accept the connection and specify a chosen subprotocol. # A list of subprotocols specified by the connecting client # will be available in self.scope['subprotocols'] await self.accept("subprotocol") # To reject the connection, call: await self.close() async def receive(self, text_data=None, bytes_data=None): # Called with either text_data or bytes_data for each frame # You can call: await self.send(text_data="Hello world!") # Or, to send a binary frame: await self.send(bytes_data="Hello world!") # Want to force-close the connection? Call: await self.close() # Or add a custom WebSocket error code! await self.close(code=4123) async def disconnect(self, close_code): # Called when the socket closes ``` -------------------------------- ### Define a Consumer for Background Tasks Source: https://github.com/django/channels/blob/main/docs/topics/worker.md Create a consumer that handles specific event types received from a channel. This example defines a consumer for a 'test.print' event. ```python class PrintConsumer(SyncConsumer): def test_print(self, message): print("Test: " + message["text"]) ``` -------------------------------- ### Daphne with IPC Supervisor Configuration Source: https://github.com/django/channels/blob/main/loadtesting/2016-09-06/README.rst Supervisor configuration for Django Channels using IPC (Inter Process Communication) with Daphne as the ASGI server. This setup is specific to single-machine deployments. ```bash [program:daphne] command = daphne -b 0.0.0.0 -p 80 testproject.asgi_for_ipc:channel_layer directory = /srv/channels/testproject/ user = root [program:worker] command = python manage.py runworker --settings=testproject.settings.channels_ipc directory = /srv/channels/testproject/ user = root [group:django_channels] programs=daphne,worker priority=999 ``` -------------------------------- ### WebsocketConsumer Example Source: https://github.com/django/channels/blob/main/docs/topics/consumers.md Handles text and binary frames for WebSocket connections. Use this for synchronous WebSocket handling. It automatically manages group membership based on the `groups` attribute. ```python from channels.generic.websocket import WebsocketConsumer class MyConsumer(WebsocketConsumer): groups = ["broadcast"] def connect(self): # Called on connection. # To accept the connection call: self.accept() # Or accept the connection and specify a chosen subprotocol. # A list of subprotocols specified by the connecting client # will be available in self.scope['subprotocols'] self.accept("subprotocol") # To reject the connection, call: self.close() def receive(self, text_data=None, bytes_data=None): # Called with either text_data or bytes_data for each frame # You can call: self.send(text_data="Hello world!") # Or, to send a binary frame: self.send(bytes_data="Hello world!") # Want to force-close the connection? Call: self.close() # Or add a custom WebSocket error code! self.close(code=4123) def disconnect(self, close_code): # Called when the socket closes ``` -------------------------------- ### Daphne with Redis Supervisor Configuration Source: https://github.com/django/channels/blob/main/loadtesting/2016-09-06/README.rst Supervisor configuration for Django Channels using Redis as the backend with Daphne as the ASGI server. This setup uses a single worker and local Redis. ```bash [program:daphne] command = daphne -b 0.0.0.0 -p 80 testproject.asgi:channel_layer directory = /srv/channels/testproject/ user = root [program:worker] command = python manage.py runworker directory = /srv/channels/testproject/ user = django-channels [group:django_channels] programs=daphne,worker priority=999 ``` -------------------------------- ### Run Tests with Pytest Source: https://github.com/django/channels/blob/main/docs/contributing.md Execute all project tests using the pytest framework. Ensure you have installed the test dependencies. ```sh pytest ``` -------------------------------- ### Testing Consumers with Django TestCase Source: https://github.com/django/channels/blob/main/docs/topics/testing.md Example of testing a Channels consumer using Django's TestCase with an HttpCommunicator. ```APIDOC ## Testing Consumers with Django TestCase ### Description This example demonstrates how to test a Channels consumer, specifically `MyConsumer`, using Django's `TestCase` and the `HttpCommunicator` helper. ### Method `TestCase.async_test_method` ### Endpoint `/test/` (simulated) ### Parameters None directly in the test method signature. ### Request Body None explicitly defined in this example. ### Request Example ```python from django.test import TestCase from channels.testing import HttpCommunicator from myproject.myapp.consumers import MyConsumer class MyTests(TestCase): async def test_my_consumer(self): communicator = HttpCommunicator(MyConsumer.as_asgi(), "GET", "/test/") response = await communicator.get_response() self.assertEqual(response["body"], b"test response") self.assertEqual(response["status"], 200) ``` ### Response #### Success Response (200) - **body** (bytes) - The response body from the consumer. - **status** (int) - The HTTP status code of the response. #### Response Example ```json { "body": "test response", "status": 200 } ``` ``` -------------------------------- ### Run Redis Server with Docker Source: https://github.com/django/channels/blob/main/docs/tutorial/part_2.md Starts a Redis server instance on port 6379 using a Docker container. This is required for the Redis-backed channel layer. ```sh $ docker run --rm -p 6379:6379 redis:7 ``` -------------------------------- ### Custom Query String Authentication Middleware Source: https://github.com/django/channels/blob/main/docs/topics/authentication.md Implement a custom ASGI middleware to authenticate users based on a user ID from the query string. This example uses database_sync_to_async for fetching user data. ```python from channels.db import database_sync_to_async @database_sync_to_async def get_user(user_id): try: return User.objects.get(id=user_id) except User.DoesNotExist: return AnonymousUser() class QueryAuthMiddleware: """ Custom middleware (insecure) that takes user IDs from the query string. """ def __init__(self, app): # Store the ASGI application we were passed self.app = app async def __call__(self, scope, receive, send): # Look up user from query string (you should also do things like # checking if it is a valid user ID, or if scope["user"] is already # populated). scope['user'] = await get_user(int(scope["query_string"])) return await self.app(scope, receive, send) ``` -------------------------------- ### Non-Specific Bug/"It Doesn't Work!" Template Source: https://github.com/django/channels/blob/main/docs/support.md This template is for issues that lack direct reproduction steps or only occur in production. It guides users on diagnosing and reporting problems effectively, directing them to the support documentation for further assistance. ```text I'm afraid we can't address issues without either direct steps to reproduce, or that only happen in a production environment, as they may not be problems in the project itself. Our support documentation (https://channels.readthedocs.io/en/latest/support.html) has details about how to take this sort of problem, diagnose it, and either fix it yourself, get help from the community, or make it into an actionable issue that we can handle. Sorry we have to direct you away like this, but we get a lot of support requests every week. If you can reduce the problem to a clear set of steps to reproduce or an example project that fails in a fresh environment, please re-open the ticket with that information. ``` -------------------------------- ### Consumer as_asgi() Method Source: https://github.com/django/channels/blob/main/docs/topics/routing.md Explains the use of the `as_asgi()` classmethod on consumers to create ASGI-compatible applications. ```APIDOC ## Consumer as_asgi() Method ### Description The `as_asgi()` classmethod is called on a Channels consumer class to return an ASGI wrapper application. This wrapper ensures that a new consumer instance is created for each incoming connection or scope, similar to Django's `as_view()` for request handling. ### Method `as_asgi()` (classmethod) ### Endpoint N/A (Method on consumer class) ### Parameters N/A ### Request Example ```python # In routing configuration: path("chat/", MyConsumer.as_asgi()) ``` ### Response Returns an ASGI application. #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Testing Consumers with pytest Source: https://github.com/django/channels/blob/main/docs/topics/testing.md Example of testing a Channels consumer using pytest and pytest-asyncio with HttpCommunicator. ```APIDOC ## Testing Consumers with pytest ### Description This example shows how to test a Channels consumer, `MyConsumer`, using `pytest` and the `pytest.mark.asyncio` decorator, along with `HttpCommunicator`. ### Method `pytest.mark.asyncio` decorated async function ### Endpoint `/test/` (simulated) ### Parameters None directly in the test function signature. ### Request Body None explicitly defined in this example. ### Request Example ```python import pytest from channels.testing import HttpCommunicator from myproject.myapp.consumers import MyConsumer @pytest.mark.asyncio async def test_my_consumer(): communicator = HttpCommunicator(MyConsumer.as_asgi(), "GET", "/test/") response = await communicator.get_response() assert response["body"] == b"test response" assert response["status"] == 200 ``` ### Response #### Success Response (200) - **body** (bytes) - The response body from the consumer. - **status** (int) - The HTTP status code of the response. #### Response Example ```json { "body": "test response", "status": 200 } ``` ``` -------------------------------- ### Configure Persistent Socket Directory Source: https://github.com/django/channels/blob/main/docs/deploying.md Make the /run/daphne folder persistent across server reboots by creating a tmpfiles.d configuration file. ```text $ d /run/daphne 0755 ``` -------------------------------- ### Get HTTP Response Source: https://github.com/django/channels/blob/main/docs/topics/testing.md Wait for the HTTP response from the HttpCommunicator. The response body is expected to be a bytestring. ```python response = await communicator.get_response() assert response["body"] == b"test response" ``` -------------------------------- ### Add Daphne to INSTALLED_APPS Source: https://github.com/django/channels/blob/main/docs/tutorial/part_1.md Include 'daphne' in your INSTALLED_APPS setting to enable its features, including the ASGI version of the runserver command. Place it at the top to ensure it takes precedence. ```python # mysite/settings.py INSTALLED_APPS = [ 'daphne', 'chat', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ] ``` -------------------------------- ### Create Django Project Source: https://github.com/django/channels/blob/main/docs/tutorial/part_1.md Use `django-admin` to create a new Django project named 'mysite'. This command should be run from the directory where you want to store your code. ```sh $ django-admin startproject mysite ``` -------------------------------- ### Set ASGI_APPLICATION in Settings Source: https://github.com/django/channels/blob/main/docs/tutorial/part_1.md Configure the ASGI_APPLICATION setting to point to your project's ASGI application entry point. This tells Daphne where to find your routing configuration. ```python # mysite/settings.py # Daphne ASGI_APPLICATION = "mysite.asgi.application" ``` -------------------------------- ### Run Daphne ASGI Server Source: https://github.com/django/channels/blob/main/docs/deploying.md Use this command to run the Daphne ASGI server, supplying your project's application. Ensure you have an asgi.py file. ```sh daphne myproject.asgi:application ``` -------------------------------- ### Instantiate ChannelNameRouter Source: https://github.com/django/channels/blob/main/docs/topics/routing.md Instantiate ChannelNameRouter with a dictionary mapping channel names to ASGI applications. ```python ChannelNameRouter({ "thumbnails-generate": some_app, "thumbnails-delete": some_other_app, }) ``` -------------------------------- ### Get Channel Layer Instance Source: https://github.com/django/channels/blob/main/docs/topics/channel_layers.md Retrieve the channel layer instance when not within a consumer's scope. Ensure `channels` is configured in your Django settings. ```python from channels.layers import get_channel_layer channel_layer = get_channel_layer() ``` -------------------------------- ### Configure Django Channels with Redis Source: https://github.com/django/channels/blob/main/docs/tutorial/part_2.md Set up the ASGI application and configure the default channel layer to use Redis. Ensure Redis is running on the specified host and port. ```python ASGI_APPLICATION = "mysite.asgi.application" CHANNEL_LAYERS = { "default": { "BACKEND": "channels_redis.core.RedisChannelLayer", "CONFIG": { "hosts": [("127.0.0.1", 6379)], }, }, } ``` -------------------------------- ### List Available Tox Environments Source: https://github.com/django/channels/blob/main/docs/contributing.md View all the available test environments configured in the tox.ini file. This helps in understanding the different testing configurations. ```sh $ tox -l ``` -------------------------------- ### Gunicorn Supervisor Configuration Source: https://github.com/django/channels/blob/main/loadtesting/2016-09-06/README.rst Supervisor configuration for running a standard Django environment with Gunicorn to handle HTTP requests. This setup is used as a baseline for comparison. ```bash [program:gunicorn] command = gunicorn testproject.wsgi_no_channels -b 0.0.0.0:80 directory = /srv/channels/testproject/ user = root [group:django_http] programs=gunicorn priority=999 ``` -------------------------------- ### Broadcasting Messages to a Group Source: https://github.com/django/channels/blob/main/docs/topics/channel_layers.md Example of a WebSocket consumer that receives a message and broadcasts it to all consumers in the 'chat' group. It defines a `chat_message` handler to send the received text. ```python class ChatConsumer(WebsocketConsumer): ... def receive(self, text_data): async_to_sync(self.channel_layer.group_send)( "chat", { "type": "chat.message", "text": text_data, }, ) def chat_message(self, event): self.send(text_data=event["text"]) ``` -------------------------------- ### Instantiate WebsocketCommunicator Source: https://github.com/django/channels/blob/main/docs/topics/testing.md Instantiate WebsocketCommunicator to test WebSocket consumers. The connect() method returns connection status and subprotocol. ```python from channels.testing import WebsocketCommunicator communicator = WebsocketCommunicator(SimpleWebsocketApp.as_asgi(), "/testws/") connected, subprotocol = await communicator.connect() assert connected ``` -------------------------------- ### Basic URL Routing for ASGI Applications Source: https://github.com/django/channels/blob/main/docs/introduction.md Combines multiple consumers into a single ASGI application using URL patterns. Suitable for simple routing needs. ```python application = URLRouter([ path("chat/admin/", AdminChatConsumer.as_asgi()), path("chat/", PublicChatConsumer.as_asgi()), ]) ``` -------------------------------- ### Removing Consumer from a Group Source: https://github.com/django/channels/blob/main/docs/topics/channel_layers.md Example of a WebSocket consumer that removes its channel name from a group named 'chat' upon disconnection. This requires the use of `async_to_sync` for synchronous consumers. ```python def disconnect(self, close_code): async_to_sync(self.channel_layer.group_discard)( ``` -------------------------------- ### Adding Consumer to a Group Source: https://github.com/django/channels/blob/main/docs/topics/channel_layers.md Example of a WebSocket consumer that adds its channel name to a group named 'chat' upon connection. This requires the use of `async_to_sync` for synchronous consumers. ```python # This example uses WebSocket consumer, which is synchronous, and so # needs the async channel layer functions to be converted. from asgiref.sync import async_to_sync class ChatConsumer(WebsocketConsumer): def connect(self): async_to_sync(self.channel_layer.group_add)( ``` -------------------------------- ### Add Chat App to INSTALLED_APPS Source: https://github.com/django/channels/blob/main/docs/tutorial/part_1.md Configure your Django project's `settings.py` file by adding 'chat' to the `INSTALLED_APPS` list to register the new app. ```python # mysite/settings.py INSTALLED_APPS = [ 'chat', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ] ``` -------------------------------- ### Add Daphne to INSTALLED_APPS Source: https://github.com/django/channels/blob/main/docs/installation.md Include 'daphne' at the beginning of your INSTALLED_APPS setting to ensure Daphne's runserver command integrates correctly with Django. ```python INSTALLED_APPS = ( "daphne", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.sites", ... ) ``` -------------------------------- ### Run Tox with Pytest Arguments Source: https://github.com/django/channels/blob/main/docs/contributing.md Forward arguments to pytest when running tests via tox. This example passes the '-s' option to pytest, which is useful for debugging with pdb. ```sh tox -e py310-dj41 -- -s ``` -------------------------------- ### Django ASGI Application with Channels Integration Source: https://github.com/django/channels/blob/main/docs/introduction.md Sets up a Django ASGI application integrating HTTP and WebSocket protocols with authentication and origin validation. Initializes Django ORM early. ```python from django.core.asgi import get_asgi_application from django.urls import re_path # Initialize Django ASGI application early to ensure the AppRegistry # is populated before importing code that may import ORM models. django_asgi_app = get_asgi_application() from channels.routing import ProtocolTypeRouter, URLRouter from channels.auth import AuthMiddlewareStack from channels.security.websocket import AllowedHostsOriginValidator application = ProtocolTypeRouter({ "http": django_asgi_app, "websocket": AllowedHostsOriginValidator( AuthMiddlewareStack( URLRouter([ re_path(r"^front(end)/$", consumers.AsyncChatConsumer.as_asgi()), ]) ) ), }) ``` -------------------------------- ### Run Project Tests with Tox Source: https://github.com/django/channels/blob/main/CONTRIBUTING.rst Execute the project's test suite using Tox. This command ensures that your changes pass all defined test environments. ```sh tox ``` -------------------------------- ### Run the Channels Worker Command Source: https://github.com/django/channels/blob/main/docs/topics/worker.md Execute the `runworker` management command to start a process that listens for and handles tasks on specified channels. Ensure the worker is running for events to be processed. ```text python manage.py runworker thumbnails-generate thumbnails-delete ``` -------------------------------- ### Configure Django Channels ASGI Application Source: https://github.com/django/channels/blob/main/docs/includes/asgi_example.md Set up the ASGI application to handle HTTP and WebSocket traffic. Ensure Django settings are loaded early and define routing for different protocols. ```python import os from channels.auth import AuthMiddlewareStack from channels.routing import ProtocolTypeRouter, URLRouter from channels.security.websocket import AllowedHostsOriginValidator from django.core.asgi import get_asgi_application from django.urls import path os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") # Initialize Django ASGI application early to ensure the AppRegistry # is populated before importing code that may import ORM models. django_asgi_app = get_asgi_application() from chat.consumers import AdminChatConsumer, PublicChatConsumer application = ProtocolTypeRouter({ # Django's ASGI application to handle traditional HTTP requests "http": django_asgi_app, # WebSocket chat handler "websocket": AllowedHostsOriginValidator( AuthMiddlewareStack( URLRouter([ path("chat/admin/", AdminChatConsumer.as_asgi()), path("chat/", PublicChatConsumer.as_asgi()), ]) ) ), }) ``` -------------------------------- ### ChatConsumer with Channel Name Handling Source: https://github.com/django/channels/blob/main/docs/topics/channel_layers.md Example of a WebSocket consumer that stores its channel name in the database upon connection and removes it upon disconnection. It also defines a handler for 'chat.message' events. ```python class ChatConsumer(WebsocketConsumer): def connect(self): # Make a database row with our channel name Clients.objects.create(channel_name=self.channel_name) def disconnect(self, close_code): # Note that in some rare cases (power loss, etc) disconnect may fail # to run; this naive example would leave zombie channel names around. Clients.objects.filter(channel_name=self.channel_name).delete() def chat_message(self, event): # Handles the "chat.message" event when it's sent to us. self.send(text_data=event["text"]) ``` -------------------------------- ### Handle Incoming Channel Layer Message Source: https://github.com/django/channels/blob/main/docs/topics/channel_layers.md Example of a consumer method that handles an incoming channel layer message. The method name corresponds to the `type` field of the message, with periods replaced by underscores. ```python async def chat_message(self, event): """ Called when someone has messaged our chat. """ # Send a message down to the client await self.send_json( { "msg_type": settings.MSG_TYPE_MESSAGE, "room": event["room_id"], "username": event["username"], "message": event["message"], }, ) ``` -------------------------------- ### Serve Static Files with ChannelsLiveServerTestCase Source: https://github.com/django/channels/blob/main/docs/topics/testing.md Set `serve_static = True` when subclassing ChannelsLiveServerTestCase to enable serving static files during tests. This is similar to Django's StaticLiveServerTestCase and eliminates the need to run `collectstatic`. ```python class LiveStaticTests(ChannelsLiveServerTestCase): serve_static = True ``` -------------------------------- ### Configure Test Database for Live Tests Source: https://github.com/django/channels/blob/main/docs/topics/testing.md Configure a file-based SQLite database for live tests by specifying a test database name in your settings. This is required because in-memory databases cannot be used for live tests. ```python DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", "NAME": os.path.join(BASE_DIR, "db.sqlite3"), "TEST": { "NAME": os.path.join(BASE_DIR, "db_test.sqlite3"), }, }, } ``` -------------------------------- ### URLRouter with Regex Paths Source: https://github.com/django/channels/blob/main/docs/topics/routing.md URLRouter routes connections based on the HTTP path using Django's path or re_path objects. This example demonstrates routing with regular expressions, including capturing groups. ```python URLRouter([ re_path(r"^longpoll/$", LongPollConsumer.as_asgi()), re_path(r"^notifications/(?P\\w+)/$", LongPollConsumer.as_asgi()), re_path(r"", get_asgi_application()), ]) ``` -------------------------------- ### Implement Basic HTTP Endpoint with AsyncHttpConsumer Source: https://github.com/django/channels/blob/main/docs/topics/consumers.md Implement the `handle` method to process requests and send responses. The method receives the entire request body and expects a bytestring for the response body. Headers can be a list of tuples or a dictionary. ```python from channels.generic.http import AsyncHttpConsumer class BasicHttpConsumer(AsyncHttpConsumer): async def handle(self, body): await asyncio.sleep(10) await self.send_response(200, b"Your response bytes", headers=[ (b"Content-Type", b"text/plain"), ]) ``` -------------------------------- ### Run Tox Tests for Specific Environments Source: https://github.com/django/channels/blob/main/docs/contributing.md Execute tests using tox for a specified set of Python and Django versions. This example runs tests for Python 3.10 with Django 4.1 and Django main branch. ```sh $ tox -e py310-dj41,py310-djmain ``` -------------------------------- ### Access Session Data in Consumer Source: https://github.com/django/channels/blob/main/docs/topics/sessions.md Access the session dictionary via self.scope["session"] within your consumer to read or modify session data. This example shows setting a random integer to the session. ```python class ChatConsumer(WebsocketConsumer): def connect(self, event): self.scope["session"]["seed"] = random.randint(1, 1000) ``` -------------------------------- ### Log User In within AsyncWebsocketConsumer Source: https://github.com/django/channels/blob/main/docs/topics/authentication.md Use `await login(self.scope, user)` to log a user into the current session within an `AsyncWebsocketConsumer`. Remember to call `await database_sync_to_async(self.scope["session"].save)()` afterwards to persist the session changes. ```python from channels.auth import login class ChatConsumer(AsyncWebsocketConsumer): ... async def receive(self, text_data): ... # login the user to this session. await login(self.scope, user) # save the session (if the session backend does not access the db you can use `sync_to_async`) await database_sync_to_async(self.scope["session"].save)() ``` -------------------------------- ### Configure Daphne Port and IP Source: https://github.com/django/channels/blob/main/docs/deploying.md Specify the IP address and port Daphne should bind to. This is useful for controlling network accessibility. ```sh daphne -b 0.0.0.0 -p 8001 myproject.asgi:application ``` -------------------------------- ### Supervisor Configuration for Daphne Source: https://github.com/django/channels/blob/main/docs/deploying.md Configure Supervisor to manage Daphne processes, using a TCP socket for Nginx communication and specifying process details. Adjust 'directory' and 'mysite.asgi' to match your project. ```ini [fcgi-program:asgi] socket=tcp://localhost:8000 directory=/my/app/path command=daphne -u /run/daphne/daphne%(process_num)d.sock --fd 0 --access-log - --proxy-headers mysite.asgi:application numprocs=4 process_name=asgi%(process_num)d autostart=true autorestart=true ``` -------------------------------- ### Configure INSTALLED_APPS for Daphne Source: https://github.com/django/channels/blob/main/CHANGELOG.txt Add 'daphne' to your Django settings INSTALLED_APPS to enable its integration. This is required for Channels v4.0.0 and later. ```python INSTALLED_APPS = [ "daphne", ... ] ``` -------------------------------- ### Basic ASGI Application Structure Source: https://github.com/django/channels/blob/main/docs/asgi.md An ASGI application is a single asynchronous callable that accepts a scope dictionary and two callables, receive and send. Applications are instantiated once per connection scope. ```python async def application(scope, receive, send): event = await receive() ... await send({"type": "websocket.send", ...}) ``` -------------------------------- ### Create Daphne Socket Directory Source: https://github.com/django/channels/blob/main/docs/deploying.md Create the run directory for sockets used by Supervisor. Ensure this directory is owned by the correct user if running Supervisor under a different user. ```sh sudo mkdir /run/daphne/ ``` ```sh sudo chown . /run/daphne/ ``` -------------------------------- ### Configure ASGI Application Routing Source: https://github.com/django/channels/blob/main/docs/tutorial/part_2.md Sets up the ASGI application with routing for HTTP and WebSocket connections. WebSocket connections are processed through authentication and URL routing. ```python from django.core.asgi import get_asgi_application from chat.routing import websocket_urlpatterns application = ProtocolTypeRouter( { "http": get_asgi_application(), "websocket": AllowedHostsOriginValidator( AuthMiddlewareStack(URLRouter(websocket_urlpatterns)) ), } ) ``` -------------------------------- ### Set ASGI_APPLICATION Setting Source: https://github.com/django/channels/blob/main/docs/installation.md Configure your project's settings to point ASGI_APPLICATION to the routing object defined in your asgi.py file. ```python ASGI_APPLICATION = "myproject.asgi.application" ``` -------------------------------- ### ASGI Configuration for Channels Source: https://github.com/django/channels/blob/main/docs/tutorial/part_1.md This Python code adjusts the mysite/asgi.py file to configure the ASGI application for Channels. This is necessary for Channels to handle incoming requests. ```python import os from django.core.asgi import get_asgi_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") application = get_asgi_application() ``` -------------------------------- ### Configure Redis Channel Layer Source: https://github.com/django/channels/blob/main/docs/topics/channel_layers.md Set up the Redis channel layer for production use. Requires the `channels_redis` package. Assumes Redis is running on localhost:6379. ```python CHANNEL_LAYERS = { "default": { "BACKEND": "channels_redis.core.RedisChannelLayer", "CONFIG": { "hosts": [("127.0.0.1", 6379)], }, }, } ``` -------------------------------- ### Run Linters with Tox Source: https://github.com/django/channels/blob/main/docs/contributing.md Execute the project's linters using the 'qa' tox environment. This helps ensure code quality and adherence to project standards. ```sh tox -e qa ```