Access Consumer from View to push api-received data to User via WebSocket (Django-Channelsv2.2 & DRF)

Viewed 856

I found myself struggling to find a way to push data to Consumer (Django Channels v.2.2) from View (APIView Django-rest-framework) or distributed task (Celery/RabbitMQ directly)

I'd really appreciate any code sample that would allow me to access the consumer from View as the trigger itself is the input device, not a web, so I can make API call from it, so I need the connector.

Django Channels v.2.2, DjangoChannelsRestFramework, mostly all the cases described here: https://channels.readthedocs.io/en/latest/community.html as well as correlating questions @stackoverflow

consumers.py

class BasicConsumer(AsyncConsumer):
    async def websocket_connect(self, event):
        print('connected', event)
        await self.send({
            "type": "websocket.accept"
        })
        # await self.send({
        #     "type": "websocket.send",
        #     "text": "Hello world"
        # })

    async def websocket_receive(self, event):
        print('receive', event)
        front_text = event.get('text', None)
        if front_text is not None:
            loaded_dict_data = json.loads(front_text)
            msg = loaded_dict_data.get('message')
            print(msg)
            user = self.scope['user']

            if user.is_authenticated:
                username = user.username
            myResponse = {
                'message': msg,
                'username': username
            }
            await self.send({
                "type": "websocket.send",
                "text": json.dumps(myResponse)
            })

    async def websocket_disconnect(self, event):
        print('disconnect', event)

    @database_sync_to_async
    def get_thread(self, user, other_username):
        return Thread.objects.get_or_new(user, other_username)[0]

views.py

class BasicView(APIView):
    def post(self, request):
        serializer = BasicViewSerializer(data=request.data)
        if serializer.is_valid():
           triggerConsumer(serializer.validated_data)
1 Answers

I think it would be better to define a channel name and send data to it.

from asgiref.sync import async_to_sync
async_to_sync(channel_layer.send)("channel_name", {...})

you can see the full document here doc

Related