I'm using django-channels to organize my websockets on backend. Right now everything is working alright except of message sending to the front-end when info in db is changed. There is http endpoint to change model.
Here is my websocket consumer
import asyncio
from asgiref.sync import async_to_sync, sync_to_async
from channels.generic.websocket import AsyncJsonWebsocketConsumer
from rest_framework.response import Response
from rest_framework import status
from channels.db import database_sync_to_async
# models and serializers
from billing.models import Billing
from billing.serializers import BillingSerializer
from customers.models import Customer
from customers.serializers import CustomersSerializer
from shipping.models import Shipping
from shipping.serializers import ShippingSerializer
from .models import Order
from .serializers import OrdersSerializer
from .views import OrdersViewSet
from .exceptions import ClientError
from .utils import get_orders_or_error, get_orders_or_warning
class OrdersConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
orders = await get_orders_or_warning()
if 'user' in self.scope:
await self.close()
else:
await self.accept()
self.orders = set(orders)
# await self.create_order(content)
async def receive_json(self, content):
command = content.get('command', None)
orders = await get_orders_or_warning()
# print(list(self.orders))
# print(set(orders))
try:
if command == "join":
await self.join_room(JWT_Token=content['token'])
elif command == "leave":
await self.leave_room()
elif command == "send":
await self.send_room(content['message'])
except ClientError as e:
await self.send_json({"error": e.code})
async def disconnect(self, code):
for room_id in list(self.rooms):
try:
self.send_json({
'type': 'CLOSE',
'message': "Socket closed"
})
await self.leave_room(content['token'])
except ClientError:
pass
async def join_room(self, JWT_Token):
orders = await get_orders_or_warning()
serializer = OrdersSerializer(orders, many=True)
# print('serializer', serializer)
if self.orders != set(orders):
await self.send_json(
{
'type': 'orders',
'data': json.dumps(serializer.data),
},
)
await self.send_json(
{
'type': 'orders',
'data': json.dumps(serializer.data),
},
)
async def leave_room(self, JWT_Token):
await self.channel_layer.group_send(
orders.group_name,
{
'type': 'orders.leave',
'JWT_Token': JWT_Token
}
)
self.rooms.discard()
await self.channel_layer.group_discard(
orders.group_name,
self.channel_name
)
await self.send_json({
"leave": str(room_id),
})
async def send_room(self, message):
if room_id not in self.rooms:
raise ClientError("ROOM_ACCESS_DENIED")
orders = await get_orders_or_warning()
serializer = OrdersSerializer(orders, many=True)
await self.send_json(
{
'type': 'orders.give',
'data': json.dumps(serializer.data)
}
)
await self.send(text_data=json.dumps({
'message': message
}))
async def orders_leave(self, event):
await self.send_json(
{
'type': 'LEAVE',
'room': event["room_id"],
'username': event["username"]
}
)
Here is my routing file
application = ProtocolTypeRouter({
'websocket': (
URLRouter([
url('orders/', OrdersConsumer),
])
)
})
I want to get all data with front-end when some changes happened. Can this be done with current consumer? And if yes, how? I've looked too many info sources i think and now I'm kinda confused how i can actually do this.
I rly don't want to rewrite the structure, if it's possible. If you can explain how and why I need to write it the way you say I will be very grateful
You can use signals to monitor the change and send a message to the consumer using the approach defined in the docs on how to interact with the consumer from the outside
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With