2

I have created a chat app following the Django Channels documentation tutorial. Right now I want to send a message outside of consumers.py from views.py of another app. However, every time I trigger that function my chat_message function in the consumers class doesn't fire. The chat_message function is otherwise operating normally within the consumers scope. Below is the traceback of me opening a browser tab of the chat page with websockets and then logging in from a different browser. The "ccc" in the chat_message function did not print. Any ideas on what I have missed out on using channels outside of consumers?

part of the login function in users.views.py

...
channel_layer = get_channel_layer()
print("channel_layer: "+ str(channel_layer))
async_to_sync(channel_layer.group_send(
   "chat_hi", {
   "type": "chat.message",
   "message": "from views",
}))
...

traceback

...
WebSocket HANDSHAKING /ws/chat/abc/ [127.0.0.1:56478]
chat_abc
WebSocket CONNECT /ws/chat/abc/ [127.0.0.1:56478]
channel_layer: RedisChannelLayer(hosts=[{'address': ('127.0.0.1', 6379)}])
HTTP POST /accounts/login/ 302 [0.97, 127.0.0.1:54362]
...

chat.consumers.py

class OnlineFriends(AsyncWebsocketConsumer):
        async def connect(self):
            self.room_name = self.scope['url_route']['kwargs']['room_name']
            self.room_group_name = 'chat_%s' % self.room_name
            print(self.room_group_name)
            await self.channel_layer.group_add(
                self.room_group_name,
                self.channel_name
            )

            await self.accept()

        async def disconnect(self, close_code):
            print("aa")

            await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

        async def receive(self, text_data):
            text_data_json = json.loads(text_data)
            message = text_data_json['message']

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

        async def chat_message(self, event):
            print("ccc")
            message = event['message']

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

chat.routing.py

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

asgi.py

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "music.settings")

application = ProtocolTypeRouter({
  "http": get_asgi_application(),
  "websocket": AuthMiddlewareStack(
        URLRouter(
            chat.routing.websocket_urlpatterns,
        )
    ),
})

settings.py

ASGI_APPLICATION = "music.asgi.application"

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

1 Answer 1

4

You are using async_to_sync wrong. In your code you are calling channel_layer.group_send right away. The proper way to do it is as follows:

async_to_sync(channel_layer.group_send)(room.channel_name, {
            'type': 'chat_message',
            'data': {'message': 'from views'}
        })

Check the last code snippet here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.