skip to Main Content

i want to create chat app, i follow the https://channels.readthedocs.io/en/latest/tutorial/part_2.html here,

chat/
    __init__.py
    routing.py
    urls.py
    settings.py
    wsgi.py

i added this code to my routing.py

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import chat.routing

application = ProtocolTypeRouter({
    # (http->django views is added by default)
    'websocket': AuthMiddlewareStack(
        URLRouter(
            chat.routing.websocket_urlpatterns
        )
    ),
})

in my settings.py

ASGI_APPLICATION = 'Accounting.routing.application'
CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [('127.0.0.1', 6379)],
        },
    },
}

in my urls.py

urlpatterns = [
    path('chat/', include('chat.urls')),
    path('admin/', admin.site.urls),
]

in my chat app

chat/
    __init__.py
    consumers.py
    routing.py
    templates/
        chat/
            index.html
            room.html
    urls.py
    views.py

i have consumers.py

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

class ChatConsumer(WebsocketConsumer):
    def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        self.room_group_name = 'chat_%s' % self.room_name

        # Join room group
        async_to_sync(self.channel_layer.group_add)(
            self.room_group_name,
            self.channel_name
        )

        self.accept()

    def disconnect(self, close_code):
        # Leave room group
        async_to_sync(self.channel_layer.group_discard)(
            self.room_group_name,
            self.channel_name
        )

    # Receive message from WebSocket
    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']

        # Send message to room group
        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': message
            }
        )

    # Receive message from room group
    def chat_message(self, event):
        message = event['message']

        # Send message to WebSocket
        self.send(text_data=json.dumps({
            'message': message
        }))

this is the code in my chat>routing.py

from django.urls import re_path

from . import consumers

websocket_urlpatterns = [
    re_path(r'ws/chat/(?P<room_name>w+)/$', consumers.ChatConsumer),
]

in my chat>views.py

from django.shortcuts import render

def index(request):
    return render(request, 'chat/index.html', {})

def room(request, room_name):
    return render(request, 'chat/room.html', {
        'room_name': room_name
    })

i have urls.py in my chat app

from django.urls import path

from . import views
app_name = 'chat'
urlpatterns = [
    path('', views.index, name='index'),
    path('<str:room_name>/', views.room, name='room'),
]

i follow all the direction, i copy paste the code, the placement of py, everything in the turorial, but still i get this error

enter image description here

did i miss something?

UPDATE

enter image description here

when i tried this in my pycharm terminal
docker run -p 6379:6379 -d redis:2.8

enter image description here

5

Answers


  1. a few things have issues here.

    1) you are mixing async and sync consumer code.

    I suggest just using the async consumer all you methods then should be async methods.

    It looks like you are calling get_thread from a sync context but get_thread has been wrapped in database_sync_to_async so needs to be Called from an async context (and needs to be awaited).

    you also need to await self.channel_layer.group_add

    2) in your ThreadView you have a ChatMessage.objects.create here you should also send a message over the thread channel group.

    from channels.layers import get_channel_layer
    channel_layer = get_channel_layer()
    
    async_to_sync(channel_layer.group_send)(f"thread_{thread.id}", {"type": "chat.message", "text": ...})
    

    you also need to save the Chat message to the DB in your websocket_receive.

    Login or Signup to reply.
  2. I think in your settings.py file a template variable called CHANNEL_LAYER is enabled (that is the exact cause of the error), so try to remove this piece of code from project/settings.py

    CHANNEL_LAYERS = {
        'default': {
            'BACKEND': '',
            'CONFIG': {
               "hosts":[127.0.0.1],
            },
        },
    }
    

    In my case it was the root cause of the error. If it doesn’t work try to change your chat/routing.py file.

    Login or Signup to reply.
  3. ADD ".as_asgi()"

    from django.urls import re_path
    
    from . import consumers
    
    websocket_urlpatterns = [
        re_path(r'ws/chat/(?P<room_name>w+)/$', consumers.ChatConsumer.as_asgi()),
    ]
    
    Login or Signup to reply.
  4. I got into the same problem, its the server disconnected issue and that causes all these.
    https://github.com/tporadowski/redis/releases/tag/v5.0.9
    Download the latest version and run the redis-server application. It solved my problem

    Login or Signup to reply.
  5. If you’re in linux

    1. First install docker by run this command – sudo snap install docker
    2. Then run this command – sudo chmod 666 /var/run/docker.sock
    3. Then run this command docker run -p 6379:6379 -d redis:5 and start Django server. It will probably resolve that issue. It worked for me and I guess it is pretty much the same for Windows and Mac.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search