如何使用Django通道将新创建的数据推送到客户端而不重新加载并且不完全改变现有的普通视图代码

How to use Django channels to push newly created data to client side without reloading and not completely changing the existing normal view code

大家好,我是 django 和 django 频道的新手。我对频道有一点疑问。例如,如果我有一个 post 模型并创建了一个 post,用户要查看 post,他们需要重新加载页面或者我们需要将他们重定向到查看所有 post 的列表页面。

如果我想将新创建的post推送到前端或客户端而不需要他们重新加载页面怎么办?我们可以为此使用渠道吗?如果我们为此目的使用通道,我们是否需要重写我们在普通视图中编写的所有代码或添加一个片段代码,例如在创建时发送信号并且 运行 一个 async 函数就可以解决问题?实施起来难吗?

谢谢

如果我想将新创建的 post 推送到前端或客户端而不需要他们重新加载页面怎么办?
是的,但需要注意的是,如果用户(在客户端上)在 页面上,则您必须缓存之前写入的所有 post。这对于一个小项目来说不是问题,但如果它们太多 post ,加载就会花费太多时间。

我们可以为此使用频道吗?是

如果我们为此目的使用通道,我们是否需要重写我们在普通视图中编写的所有代码或添加片段代码,例如在创建时发送信号并且 运行 异步函数将完成把戏?
是也不是,因为你已经使用了 [django-rest-framework(DRF)],rest-framework 只能在 HTTP 协议上工作;当您使用 websockets 时,您正在使用 WS 协议,从而处理事件 django-channels 拥有消费者,就像 django 和 DRF 中的视图一样。但是你可以(你应该保持代码的健壮性)使用你为 [django-rest-framework].

编写的序列化程序

为了证明这一点,用户写了一个 post 并且你在你的 django-channel AsyncConsumer 上收到了它,你可以使用这样的东西:-

from channels.db import database_sync_to_async
@database_sync_to_async
    async def save_post(self, data):
        serializer = PostSerializer(data=data)
        serializer.is_valid(raise_exception=True)
        x = serializer.create(serializer.validated_data)#this will create the post
        return PostSerializer(x).data #this will return the serialized post data

由于 django-channels AsyncConsumer 将所有事件都写在一个异步函数中 保存一个新的 post 是一个同步函数,我们需要使用一个“@database_sync_to_async”; (确保在调用 save_post 函数时使用 await-keyword)。

回答后半题可以使用django-signals吗? 是的,修改上面的代码来调用那个 django-signal 而不是在上面的“save_post”函数中使用序列化器,你可以序列化 django-signals 中的数据。 但我相信上述方法可以解决问题。

据我了解,我认为您想通知用户有关新 post 的信息,因为每个用户都应连接到同一频道组,并且一旦 save_post 功能完成调度带有通知的该组中的事件。

#inside the signals.py file
from .models.py import <Post-model>
from django.db.models.signals import post_save
from django.dispatch import receiver
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync #since everything in django
                                       #is running synchronously.

"""
when the post gets created; the below receiver function would run.
"""
@receiver(post_save,sender=<Post-model>)
def notify_new_post(sender,instance,created,**kwargs)
    if created:
        channel_layer = get_channel_layer()
        async_to_sync(channel_layer.group_send)(
            group=<group_name>,#the group/room that will receive the broadcast
            message= {
                'type':"<name of the event>",
                'payload':{<whatever notification you want to send>}
                #before writing that payload make sure what type of 
                #channels you are using if you are using a 
                #"AsyncWebsocketConsumer" the payload should be in the 
                #appropriate type thereby use json.dumps to convert it to JSON.
                #if you are using "AsyncJsonWebsocketConsumer" then you don't 
                #have to do it [this is just for precautionary].
            }
)

希望这对您有所帮助,如果没有请继续询问此主题。