0

I want to send events (json strings) via websocket to all clients (to all who established connection via websocket). My code:

I think that asgi and routing are ok

asgi.py

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'base_app.settings')
django.setup()
application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(
        URLRouter(
            websocket_urlpatterns
        )
    ),
})

routing.py

from api_producer.consumers import EventWebSocket

websocket_urlpatterns = [
    url('ws/start/', EventWebSocket.as_asgi()),
]

The problematic point: Some function generates events and I want to send these events to the clients

from api_producer.consumers import EventWebSocket

def event_producer():
    my_socket = EventWebSocket()
    my_socket.receive("Some_text")

consumers.py

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


class EventWebSocket(WebsocketConsumer):
    def connect(self):
        self.channel_name = "CHANNEL_1"
        print("CALL_ACCEPT")
        async_to_sync(self.channel_layer.group_add)("global", self.channel_name)
        self.accept()

    def disconnect(self, close_code):
        async_to_sync(self.channel_layer.group_discard)("global", self.channel_name)

    def receive(self, text_data):
        print("RRR_ receive ", text_data)
        async_to_sync(self.channel_layer.group_send)(
            "global",
            {
                "type": "global.message",
                "text": text_data,
            },
        )

    def chat_message(self, event):
        print("CHAT_MESSAGE")
        self.send(text_data=event["text"])
    
    def global_event(self, event):
        print("GLOB_MESSAGE")
        self.send(text_data=event["text"])

My actions: 1 Go to websocketKing and send request ws://127.0.0.1:8000/ws/start/. Log output:

WebSocket HANDSHAKING /ws/start/ [127.0.0.1:37194]
WebSocket HANDSHAKING /ws/start/ [127.0.0.1:37194]
CALL_ACCEPT
HTTP POST /api/start_detection/ 200 [0.57, 127.0.0.1:37238] (trigger event_producer)

What is the proper way to send events?

5
  • 1
    You need to call self.accept() in the connect method of your consumer to complete the handshake and complete the connection Commented Nov 29, 2021 at 18:53
  • Thank you, added. But I have error: ``` 'EventWebSocket' object has no attribute 'channel_layer``` (in def receive()) Commented Nov 29, 2021 at 18:57
  • 1
    You shouldn't be initialising an EventWebSocket object and calling receive on it like you are in event_producer. You need to get a channel layer and send a message to a group/channel that all your consumers are members of Commented Nov 29, 2021 at 19:07
  • @IainShelvington could you please elaborate? How to get a channel layer? Commented Nov 29, 2021 at 19:11
  • added an answer that should hopefully demonstrate the idea Commented Nov 29, 2021 at 19:18

1 Answer 1

1

You should send the events via a channel layer, you can use channel layers outside of consumers like this

from channels.layers import get_channel_layer
channel_layer = get_channel_layer()

def event_producer():
    async_to_sync(channel_layer. group_send)("global", {
        "type": "global.event",
        "text": "foo"
    })

And in your consumer join the global channel that the event producer sends the events on and add a method that can be triggered by the event producer. You could reuse the "chat" channel...

class EventWebSocket(WebsocketConsumer):
    def connect(self):
        ...
        async_to_sync(self.channel_layer.group_add)("global", self.channel_name)
        self.accept()

    ...

    def global_event(self, event):
        self.send(text_data=event["text"])
Sign up to request clarification or add additional context in comments.

1 Comment

Updated my code according to your post. But I don't receive any events (no GLOB_MESSAGE and CHAT_MESSAGE output in logs)

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.