Skip to main content
Code Review

Return to Question

Notice removed Canonical answer required by Community Bot
Bounty Ended with no winning answer by Community Bot
Notice added Canonical answer required by drec4s
Bounty Started worth 50 reputation by drec4s
Tweeted twitter.com/StackCodeReview/status/1108654627086626816
edited tags; edited title
Link
200_success
  • 145.5k
  • 22
  • 190
  • 478

Best practice for send Sending notifications with Django channels

deleted 25 characters in body
Source Link
KIN1991
  • 211
  • 3
  • 5
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):
 print(data)
 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)
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):
 print(data)
 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)
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)
Source Link
KIN1991
  • 211
  • 3
  • 5

Best practice for send notifications with Django channels

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):
 print(data)
 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
 }
 }
 )
lang-py

AltStyle によって変換されたページ (->オリジナル) /