Как отправлять данные в websocket извне потребительских каналов django
Я пытаюсь отправить данные в websocket извне потребителя
поэтому я сделал следующее:
settings.py
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [("127.0.0.1", 6379)],
},
},
}
routing.py
from django.urls import path
from .consumers import CoinsListConsumer
websocket_urlpatterns = [
path('ws/coins/', CoinsListConsumer.as_asgi())
]
asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from apps.coins.routing import websocket_urlpatterns
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.local')
application = ProtocolTypeRouter({
'http': get_asgi_application(),
'websocket': AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
websocket_urlpatterns,
)
)
)
})
consumers.py
class CoinsListConsumer(AsyncWebsocketConsumer):
async def connect(self):
logger.info('Websocket was connected.')
await self.accept()
async def disconnect(self, code):
logger.warning('Websocket was disconnected.')
pass
async def receive(self, text_data=None, bytes_data=None):
return await super().receive(text_data, bytes_data)
ну это нормально и когда я перехожу к представлению... websocket подключается очень хорошо
но когда я хочу отправить данные в websocket.
def send_data_to_websocket_coins_list_view(data: List[Dict]) -> None:
"""Send data to websocket coins list view """
async_to_sync(channel_layer.send)(json.dumps(data))
Это не сработало и вызвало следующую ошибку
TypeError: send() missing 1 required positional argument: 'message'
Также в документации это должно работать со следующим кодом
async_to_sync(channel_layer.send)("channel_name", {...})
также не работает и вызывает следующую ошибку
AssertionError: message is not a dict
Так в чем проблема? Что мне делать?
Вам не нужно сбрасывать данные
async_to_sync(channel_layer.send)(data)
Вы можете использовать его в ApiView, например:
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
class NotificationView(APIView):
def post(self, request, *args, **kwargs):
# Process the notification
notification_data = {'message': 'New notification'}
# Send the notification to the WebSocket consumer
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
'notifications',
{'type': 'send_notification', 'text': json.dumps(notification_data)}
)
return Response(status=status.HTTP_200_OK)