11
\$\begingroup\$

I have project on Django wich use Django Channels. I use Django Channel for sending notifications to users who are subscribed to articles changes (adding/editing/deleting comments on article).

So I've chosen this way of realization: every group of channels is an article and when changes happen, script sends notification to relevant groups. My code works correctly but I have some doubts if my choice of way of realization is most appropriate for this task. I need advice what is the best practice in my case?

Solution:

consumers.py

from channels.generic.websocket import AsyncJsonWebsocketConsumer
from channels.db import database_sync_to_async
from project.apps.account.models import UserStatus
from .models import CommentSubscribe


class CommentNotificationConsumer(AsyncJsonWebsocketConsumer):

    async def connect(self):
        await self.accept()
        if not self.scope['user'].is_anonymous:
            groups = await database_sync_to_async(self.get_users_subscription)()
            await database_sync_to_async(self.change_user_status)(True)
            await self.add_subscriptions(groups)

    async def add_subscriptions(self, groups):
        for group in groups:
            await self.channel_layer.group_add(
                'article_{0}'.format(group.article_id),
                self.channel_name
            )

    async def receive_json(self, content, **kwargs):
        command = content.get('command', None)
        article_id = content.get('article_id', None)
        if command == 'subscribe':
            await self.subscribe(article_id)
        elif command == 'unsubscribe':
            await self.unsubscribe(article_id)
        else:
            await self.send_json({
                'error': 'unknown command'
            })

    async def disconnect(self, code):
        await database_sync_to_async(self.change_user_status)(False)

    async def send_notification(self, action):
        await self.send_json(action)

    async def subscribe(self, article_id):
        await self.channel_layer.group_add(
            'article_{0}'.format(article_id),
            self.channel_name
        )

    async def unsubscribe(self, article_id):
        await self.channel_layer.group_discard(
            'article_{0}'.format(article_id),
            self.channel_name
        )

    def get_users_subscription(self):
        return CommentSubscribe.objects.filter(
            user=self.scope['user']
        )

    def change_user_status(self, online):
        return UserStatus.objects.filter(
            user=self.scope['user']
        ).update(online=online)

views.py

from .notify import send_comment_notification

class CreateComment(CreateView):

    ...

    def form_valid(self, form):
        ...
        super().form_valid(form)
        send_comment_notification('create', article_id)


class UpdateComment(UpdateView):

    ...

    def form_valid(self, form):
        ...
        super().form_valid(form)
        send_comment_notification('update', article_id)


class DeleteComment(DeleteView):

    ...

    def delete(self, request, *args, **kwargs):
        ...
        send_comment_notification('delete', article_id)

notify.py

...

def send_comment_notification(action, article_id):
    channel_layer = get_channel_layer()
    group_name = 'article_{0}'.format(article_id)
    async_to_sync(channel_layer.group_send)(
        group_name,
        {
            'type': 'send.notification',
            'data': {
                'action': action
            }
        }
    )
\$\endgroup\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.