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
did i miss something?
UPDATE
when i tried this in my pycharm terminal
docker run -p 6379:6379 -d redis:2.8
5
Answers
a few things have issues here.
1) you are mixing
async
andsync
consumer code.I suggest just using the
async consumer
all you methods then should beasync
methods.It looks like you are calling
get_thread
from a sync context butget_thread
has been wrapped indatabase_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 aChatMessage.objects.create
here you should also send a message over the thread channel group.you also need to save the Chat message to the DB in your websocket_receive.
I think in your
settings.py
file a template variable calledCHANNEL_LAYER
is enabled (that is the exact cause of the error), so try to remove this piece of code from project/settings.pyIn my case it was the root cause of the error. If it doesn’t work try to change your chat/routing.py file.
ADD ".as_asgi()"
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
If you’re in linux
sudo snap install docke
rsudo chmod 666 /var/run/docker.sock
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.