python - Django-channels 在模型更改时发送消息

标签 python django django-channels

我正在使用 django-channels 在后端组织我的 websockets。 现在一切正常,除了当数据库中的信息发生变化时发送到前端的消息。有 http 端点可以更改模型。

这是我的 websocket 消费者

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"]
            }
        )

这是我的路由文件


application = ProtocolTypeRouter({
    'websocket': (
            URLRouter([
                url('orders/', OrdersConsumer),
            ])
    )
})

我想在发生一些变化时通过前端获取所有数据。这可以用当前的消费者来完成吗?如果是,怎么办?我认为我已经查看了太多的信息来源,现在我有点困惑我如何才能真正做到这一点。

如果可能的话,我真的不想重写结构。如果您能解释我如何以及为什么需要按照您所说的方式编写它,我将非常感激

最佳答案

您可以使用信号来监视更改并使用 how to interact with the consumer from the outside 上的文档中定义的方法向消费者发送消息。

关于python - Django-channels 在模型更改时发送消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58914833/

相关文章:

python - 使用 virtualenvwrapper 重命名环境

django - docker、nginx、django 以及如何提供静态文件

django-rest-framework:设置外键序列化器

websocket - 返回 django graphene 订阅中订阅事件的初始数据

python - 信令服务器性能问题 : Python vs NodeJS

python - all( generator ) 在应该返回 False 时返回 True

python - 如何在solve_ivp中使用事件函数的终端属性

python - 程序一直返回无,即使我没有定义

Django 相当于 SQL REPLACE

python - django-channels/websockets : WebSocketBadStatusException: Handshake status 200