Привет, ребята, я новичок в каналах django и django. У меня есть небольшое сомнение, связанное с каналами. Например, если у меня есть модель поста и я создал пост, чтобы пользователь мог просмотреть пост, ему нужно либо перезагрузить страницу, либо нам нужно перенаправить их на страницу списка, чтобы просмотреть все посты.
Что, если я хочу отправить только что созданный пост во внешний интерфейс или на сторону клиента, не заставляя их перезагружать страницу? Можем ли мы использовать каналы для этого? И если мы используем каналы для этой цели, нужно ли нам переписывать все коды, которые мы написали в обычных представлениях, или добавление фрагмента кода, такого как отправка сигнала при создании и запуск функции async
, поможет? Сложно реализовать?
Спасибо
Что, если я хочу отправить только что созданный пост в интерфейс или на сторону клиента без перезагрузки страницы?
ДА, но с оговоркой, что вам придется кэшировать все сообщения, написанные до этого, если пользователь (на клиенте) находится на странице <post_list>. Это не будет проблемой для небольшого проекта, но если их будет слишком много, загрузка займет слишком много времени.
Можем ли мы использовать каналы для этого? ДА
И если мы используем каналы для этой цели, нужно ли нам переписывать весь код, который мы написали в обычных представлениях, или добавление фрагмента кода, такого как отправка сигнала при создании и запуск асинхронной функции, поможет?
ДА и нет, поскольку вы использовали [django-rest-framework (DRF)], rest-framework будет работать только по протоколу HTTP; когда вы используете веб-сокеты, вы используете протокол WS, таким образом, для обработки событий django-каналы имеют потребителей, как и представления в django и DRF. Но вы можете (вы должны для поддержания надежности кода) использовать сериализаторы, которые вы написали для [django-rest-framework].
Чтобы продемонстрировать это, сценарий, в котором пользователь написал сообщение, и вы получили его на своем django-канале 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 имеет все события, записанные в асинхронной функции а сохранение нового поста — это синхронная функция, нам нужно использовать «@database_sync_to_async»; (обязательно используйте ключевое слово await при вызове функции save_post).
Чтобы ответить на вторую половину вопроса, можете ли вы использовать django-сигналы? Да, измените приведенный выше код, чтобы вызвать этот сигнал django вместо использования сериализатора в функции «save_post» выше, вы можете сериализовать данные внутри сигналов django. Но я считаю, что описанный выше метод поможет.
Насколько я понимаю, я считаю, что вы хотите уведомить пользователя о новом сообщении, поскольку каждый пользователь должен быть подключен к одной и той же группе каналов, и после завершения функции 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].
}
)
Надеюсь, это поможет, если не продолжать спрашивать в этой теме.