I sat up a system with a user, member and team models. What i am trying to achieve with sockets, is for one of the team members to notify everyone on the team about an achievement.
Clientside:
- Svelte 4.2.7API:
- Django 4.2.11
- Channels 4.1.0
Just to test out the socket logic, in the frontend, when i connect, i send a test message to the server:
function createWebSocket() { const { subscribe, set } = writable(undefined); return { subscribe, connect() { const gameSocket: WebSocket = new WebSocket('ws://'+"localhost:8000" +'/ws/game/'); gameSocket.onmessage = (e) => { const data = JSON.parse(e.data); const message = data['message']; console.log("socket message", message); }; gameSocket.onclose = (e) => { console.log("socket closed unexpectedly"); console.log(e); }; gameSocket.onopen = () => { console.log("socket connected"); this.sendMessage("Test hello!") } set(gameSocket); }, sendMessage: (message: any) => { subscribe((gameSocket) => { if (gameSocket !== null) { gameSocket.send(JSON.stringify({ 'message': message })); } })(); } };}export const gameSocket = createWebSocket();
In django i connected to redis:
CHANNEL_LAYERS = {"default": {"BACKEND": "channels_redis.core.RedisChannelLayer",'CONFIG': {"hosts": [('127.0.0.1', 6379)] } }}
my asgi.py:
import osimport game.routingfrom channels.auth import AuthMiddlewareStackfrom django.core.asgi import get_asgi_applicationfrom channels.routing import ProtocolTypeRouter, URLRouteros.environ.setdefault('DJANGO_SETTINGS_MODULE', 'game.settings')application = ProtocolTypeRouter({"http": get_asgi_application(),"websocket": AuthMiddlewareStack( URLRouter([ # god knows why i need a fkn star h *game.routing.websocket_urlpatterns ]) )})
routing.py
from django.urls import pathfrom game.consumers import GameConsumerwebsocket_urlpatterns = [ path('ws/game/', GameConsumer.as_asgi()),]
and lastly my consumer.py, where i currently just hardcode the group name to team_1. My issue is that my handler function "chat_message" is never getting called, and doesnt print "team message" to the console.
class GameConsumer(JsonWebsocketConsumer): def connect(self): print(f"Trying to connect to socket with user {self.scope['user']}") if self.scope['user'].id: print("success") # Get all teams user is a part of teams = Team.objects.filter(member__user=self.scope['user'].id) # Join some kind of room or something, one room for each existing team self.accept() for team in teams: group_name = f"team_1" print(team) async_to_sync(self.channel_layer.group_add( group_name, self.channel_name )) print(f"added to group {group_name}") else: print("User not signed in") def receive(self, text_data=None): print("got message from client") print(text_data) text_data_json = json.loads(text_data) message = text_data_json['message'] #teams = Team.objects.filter(member__user=self.scope['user']).first() async_to_sync(self.channel_layer.group_send)("team_1", {"type": "chat.message","message": message } ) print("sendt msg to all users in team") def chat_message(self, event): print("team message") print(event) message = event['message'] self.send(text_data=json.dumps({'message': message }))
My client logs "socket connected"
And my server logs:
Trying to connect to socket with user b@c.comsuccessWebSocket CONNECT /ws/game/ [127.0.0.1:49405]Team object (1)added to group team_1got message from client{"message":"Test hello!"}sendt msg to all users in team
So it seems to recieve the message from the client, but not progress past the async_to_sync where i try to emit the event to the rest of the team members.