I'm working on django channels-3.0.3, the group_send
only sends my message to the last connected channel to the connected users times.
settings
...INSTALLED_APPS = ["django.contrib.admin","django.contrib.auth","django.contrib.contenttypes","django.contrib.sessions","django.contrib.messages","django.contrib.staticfiles","chat","channels",]ASGI_APPLICATION = "cfehome.routing.application"CHANNEL_LAYERS = {"default": {"BACKEND": "channels_redis.core.RedisChannelLayer","CONFIG": {"hosts": [("127.0.0.1", 6379)], }, },}
chat/consumers.py
import asyncioimport jsonfrom django.contrib.auth import get_user_modelfrom channels.consumer import AsyncConsumerfrom channels.db import database_sync_to_asyncfrom .models import Thread, ChatMessageclass ChatConsumer(AsyncConsumer): @database_sync_to_async def get_thread(self, user, other_username): return Thread.objects.get_or_new(user, other_username)[0] async def websocket_connect(self, event): other_user = self.scope['url_route']['kwargs']['username'] me = self.scope['user'] # print("connect!") # print(me, other_user) thread_obj = await self.get_thread(me, other_user) # print(me, thread_obj) chat_room = f"thread_{thread_obj.id}" self.chat_room = chat_room await self.channel_layer.group_add( chat_room, self.channel_name ) print(f"{self.channel_name}, {self.chat_room}, {me} - connected!") await self.send({"type": "websocket.accept" }) async def websocket_receive(self, event): print("msg recevied!", event) front_text = event.get("text", None) if front_text is not None: loaded_dic_Data = json.loads(front_text) msg = loaded_dic_Data.get("message") # print(msg) user = self.scope['user'] username = "default" if user.is_authenticated: username = user.username myResponse = {"message": msg,"username": username } # brodcast msg to chatroom await self.channel_layer.group_send( self.chat_room, {"type": "chat_message","text": json.dumps(myResponse), } ) # sends the actual msg async def chat_message(self, event): await self.send({"type": "websocket.send","text": event["text"] }) async def websocket_disconnect(self, event): print("disconnect!") await self.channel_layer.group_discard( self.chat_room, self.channel_name )
in consumers.py i aslo tried async_to_sync
instated of async
and await
chat/templates/chat/threads.html (my template which renders)
{% extends "base.html" %}{% block content %}<h3>Thread for {% if user != object.first %}{{ object.first }}{% else %}{{ object.second }}{% endif %}</h3><ul id='chat-items'>{% for chat in object.chatmessage_set.all %}<li>{{ chat.message }} via {{ chat.user }}</li>{% endfor %}</ul><form id='form' method='POST'> {% csrf_token %}<input type="hidden" id="myUsername" value="{{ user.username }}">{{form.as_p }}<input type='submit' class='btn btn-primary'/></form>{% endblock %}{% block script %}<script>// websocket scriptsvar loc = window.location;var formData = $("#form")var msg = $("#id_message")var chatHoler = $("#chat-items")var me = $("#myUsername").val()var wsStart = "ws://";if(loc.protocol == "https:"){ wsStart = "wss://"};var endpoint = wsStart + loc.host + loc.pathname;var socket = new WebSocket(endpoint);console.log(endpoint)socket.onmessage = function(e){ console.log("message ",e) var chatDataMsg = JSON.parse(e.data) chatHoler.append("<li>" + chatDataMsg.message +" - " + chatDataMsg.username +"</li>")};socket.onopen = function(e){ console.log("open ",e) formData.submit(function(event){ event.preventDefault() var msgText = msg.val() // chatHoler.append("<li>" + msgText +" via " + me +"</li>") var finalData = {"message": msgText, } socket.send(JSON.stringify(finalData)) formData[0].reset() });};socket.onerror = function(e){ console.log("error ",e)};socket.onclose = function(e){ console.log("close ",e)};</script>{% endblock %}
it receive the message from a channel and send back to that channel to the number of connected channels in chat_room.
~ thanks in advance.. it's my first question on site :)
updated! here is my routing.py file
from django.conf.urls import urlfrom channels.routing import ProtocolTypeRouter, URLRouterfrom channels.auth import AuthMiddlewareStackfrom channels.security.websocket import AllowedHostsOriginValidator, OriginValidatorfrom chat.consumers import ChatConsumerapplication = ProtocolTypeRouter({"websocket": AllowedHostsOriginValidator( AuthMiddlewareStack( URLRouter( [ url(r"^messages/(?P<username>[\w.@+-]+)/$", ChatConsumer()), ] ) ) )})