'Using Django-channels3 on connecting throwing error

I am using Django-Channels3 with django-redis, following a youtube tutorial, being a newbie @ Websockets, i got no idea, why WebSocketKing Client throwing this error

Could not connect to "ws://localhost:8000/ws/test/". You may be able to find more information using Inspector/Dev Tools on this page.

Error :-

WebSocket HANDSHAKING /ws/test/ [127.0.0.1:58045]
    Exception inside application: __call__() missing 1 required positional argument: 'send'
    Traceback (most recent call last):
      File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/channels/staticfiles.py", line 44, in __call__
        return await self.application(scope, receive, send)
      File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/channels/routing.py", line 71, in __call__
        return await application(scope, receive, send)
      File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/channels/routing.py", line 150, in __call__
        return await application(
      File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/asgiref/compatibility.py", line 35, in new_application
        return await instance(receive, send)
    TypeError: __call__() missing 1 required positional argument: 'send'
    WebSocket DISCONNECT /ws/test/ [127.0.0.1:58045]

consumers.py

from channels.generic.websocket import WebsocketConsumer
from asgiref.sync import async_to_sync
import json

class TestConsumer(WebsocketConsumer):
    def connect(self):
        self.room_name = "test_consumer"
        self.room_group_name = "test_consumer_group"
        async_to_sync(self.channel_layer.group_add)(
            self.room_name, self.room_group_name
        )
        self.accept()
        self.send(text_data=json.dumps({'status' : 'connected'}))
    
    # def receive(self):
    #     pass
    
    # def disconnect(self):
    #     pass
    

asgi.py

import os

from django.core.asgi import get_asgi_application

from channels.routing import ProtocolTypeRouter, URLRouter
from django.urls import path

from home.consumers import *

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dj_channels.settings')

application = get_asgi_application()

ws_patterns = [
    path('ws/test/', TestConsumer)
]

application = ProtocolTypeRouter({
    'websocket' : URLRouter(ws_patterns)
})

Settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'channels',
    'home',
]


ROOT_URLCONF = 'dj_channels.urls'

# WSGI_APPLICATION = 'dj_channels.wsgi.application'
ASGI_APPLICATION = 'dj_channels.asgi.application'

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("localhost", 6379)],
        },
    },
}


Solution 1:[1]

In Asgi.py file use

ws_patterns = [
path('ws/test/', TestConsumer.as_asgi())
]

Instead of Using

ws_patterns = [
path('ws/test/', TestConsumer)
]

Then It should work.

Solution 2:[2]

You need to do two things to solve this problem.

  1. In asgi.py file, use
ws_patterns = [
  path('ws/test/', TestConsumer.as_asgi())
]
  1. In consumers.py file, you don't need to call async_to_sync() method.
self.channel_layer.group_add(
      'test_consumer', self.channel_name
    )

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Yogesh Agarwal
Solution 2 Al Jaber Nishad