Потребитель каналов Django не получает данные
Я пытаюсь написать потребителя websocket, который получает все непрочитанные уведомления, а также все уведомления, которые создаются, пока клиент все еще подключен к websocket.
Я могу подключиться к потребителю, и он показывает мне все активные уведомления. Проблема в том, что он не показывает мне новые уведомления, когда они создаются и отправляются из метода сохранения модели.
consumers.py
class NotificationConsumer(WebsocketConsumer):
def get_notifications(self, user):
new_followers = NotificationSerializer(Notification.objects.filter(content=1), many=True)
notifs = {
"new_followers": new_followers.data
}
return {
"count": sum(len(notif) for notif in notifs.values()),
"notifs": notifs
}
def connect(self):
user = self.scope["user"]
if user:
self.channel_name = user.username
self.room_group_name = 'notification_%s' % self.channel_name
notification = self.get_notifications(self.scope["user"])
print("Notification", notification)
self.accept()
return self.send(text_data=json.dumps(notification))
self.disconnect(401)
async def disconnect(self, close_code):
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
async def receive(self, text_data):
text_data_json = json.loads(text_data)
count = text_data_json['count']
notification_type = text_data_json['notification_type']
notification = text_data_json['notification']
print(text_data_json)
await self.channel_layer.group_send(
self.room_group_name,
{
"type": "receive",
"count": count,
"notification_type": notification_type,
"notification": notification
}
)
models.py
class Notification(models.Model):
content = models.CharField(max_length=200, choices=NOTIFICATION_CHOICES, default=1)
additional_info = models.CharField(max_length=100, blank=True)
seen = models.BooleanField(default=False)
users_notified = models.ManyToManyField("core.User", blank=True)
user_signaling = models.ForeignKey("core.User", on_delete=models.CASCADE, related_name="user_signaling")
def save(self, *args, **kwargs):
if self._state.adding:
super(Notification, self).save(*args, **kwargs)
else:
notif = Notification.objects.filter(seen=False)
data = {
"type": "receive",
"count": len(notif),
"notification_type": self.content,
"notification": self.additional_info
}
channel_layer = get_channel_layer()
for user in self.users_notified.all():
async_to_sync(channel_layer.group_send(
f"notification_{user.username}",
data
)
)
print(channel_layer)
Я проверяю наличие self._state.adding
, поэтому он будет посылать сообщение websocket только тогда, когда users_notified
уже были добавлены после создания модели.
пример использования:
notif = Notification.objects.create(
content=1,
user_signaling=user,
additional_info=f"{user.username} just followed you!"
)
notif.users_notified.add(other_user)
notif.save()
Обычно я использую сигналы, в вашем случае вы могли бы использовать сигнал post_save вместо переопределения модели save().
channel_layer = get_channel_layer()
@receiver(post_save, sender=Notification)
def notification_on_create(sender, instance, created, **kwargs) -> None:
_, _ = sender, kwargs
if created:
return None
notif = Notification.objects.filter(seen=False)
data = {
"type": "receive",
"count": len(notif),
"notification_type": instance.content,
"notification": instance.additional_info
}
for user in self.users_notified.all():
async_to_sync(channel_layer.group_send(
f"notification_{user.username}", data))