from django.contrib.sessions.models import Session
from users.models import User
class QueryAuthMiddleware:
def __init__(self, inner):
# Store the ASGI application we were passed
self.inner = inner
def __call__(self, scope):
# Look up user from query string (you should also do things like
# check it's a valid user ID, or if scope["user"] is already populated)
if scope.get("user", None) is None:
session_obj = Session.objects.get(session_key=scope["query_string"].decode("utf-8").split("=")[1])
session_decoded = session_obj.get_decoded()
scope["user"] = User.objects.get(id=session_decoded.get("_auth_user_id"))
# Return the inner application directly and let it run everything else
return self.inner(scope)
from django.conf.urls import url
from django.conf import settings
from channels.routing import ProtocolTypeRouter, URLRouter, ChannelNameRouter
from notifications.consumer import TestWebsocketConsumer, TestConsumer
from notifications.middleware.query_auth_middleware import QueryAuthMiddleware
ROOT_PATH = "" if settings.DEBUG else "/ws/"
application = ProtocolTypeRouter({
"websocket": QueryAuthMiddleware(
URLRouter([
url(f"^{ROOT_PATH}(?P<user_id>[-\w]+)/$", TestWebsocketConsumer),
])
),
"channel": ChannelNameRouter({
"user-notifications": TestConsumer,
})
})
from asgiref.sync import async_to_sync
from channels.consumer import SyncConsumer
from channels.generic.websocket import WebsocketConsumer
class TestWebsocketConsumer(WebsocketConsumer):
def websocket_connect(self, message):
async_to_sync(self.channel_layer.group_add)(str(self.scope["user"].id), "user-notifications")
self.connect()
class TestConsumer(SyncConsumer):
def notification_handler(self, message):
self.send(
{
"type": "websocket.send",
"text": message["text"]
}
)
>>> channel_layer = get_channel_layer()
>>> async_to_sync(channel_layer.send)("user-notifications", {"type": "notification.handler", "text": "My Message"})
2018-02-25 02:34:14,002 - INFO - runworker - Running worker for channels ['user-notifications']ERROR:root:Exception inside application: You must implement application_send() File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/channels/consumer.py", line 54, in __call__ await await_many_dispatch([receive, self.channel_receive], self.dispatch) File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/channels/utils.py", line 48, in await_many_dispatch await dispatch(result) File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/asgiref/sync.py", line 110, in __call__ return await asyncio.wait_for(future, timeout=None) File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/tasks.py", line 333, in wait_for return (yield from fut) File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/concurrent/futures/thread.py", line 55, in run result = self.fn(*self.args, **self.kwargs) File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/channels/db.py", line 13, in thread_handler return super().thread_handler(loop, *args, **kwargs) File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/asgiref/sync.py", line 125, in thread_handler return self.func(*args, **kwargs) File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/channels/consumer.py", line 99, in dispatch handler(message) File "/Users/muhammed/projects/xxx/my-app/app/notifications/consumer.py", line 18, in notification_handler "text": message["text"] File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/channels/consumer.py", line 107, in send self.base_send(message) File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/asgiref/sync.py", line 64, in __call__ return call_result.result() File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/concurrent/futures/_base.py", line 405, in result return self.__get_result() File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/concurrent/futures/_base.py", line 357, in __get_result raise self._exception File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/asgiref/sync.py", line 78, in main_wrap result = await self.awaitable(*args, **kwargs) File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/asgiref/server.py", line 71, in application_send raise NotImplementedError("You must implement application_send()") You must implement application_send()
# -- Channels Details
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [("localhost", 6379)]
}
}
}
ASGI_APPLICATION = "myapp.settings.channels.application"
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/c5c4bef6-0469-401a-9624-1eed4374c1cf%40googlegroups.com.--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
"channel": ChannelNameRouter({
"user-notifications": TestWebsocketConsumer,
})
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
class TestWebsocketConsumer(WebsocketConsumer):
def websocket_connect(self, message):
async_to_sync(self.channel_layer.group_add)(str(self.scope["user"].id), "user-notifications")
self.connect()
def notification_handler(self, message):
self.send(
{
"text": message["text"]
}
)
ERROR:root:Exception inside application: You must implement application_send() File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/channels/consumer.py", line 54, in __call__ await await_many_dispatch([receive, self.channel_receive], self.dispatch) File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/channels/utils.py", line 48, in await_many_dispatch await dispatch(result) File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/asgiref/sync.py", line 110, in __call__ return await asyncio.wait_for(future, timeout=None) File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/tasks.py", line 333, in wait_for return (yield from fut) File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/concurrent/futures/thread.py", line 55, in run result = self.fn(*self.args, **self.kwargs) File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/channels/db.py", line 13, in thread_handler return super().thread_handler(loop, *args, **kwargs) File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/asgiref/sync.py", line 125, in thread_handler return self.func(*args, **kwargs) File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/channels/consumer.py", line 99, in dispatch handler(message)
File "/Users/muhammed/projects/xxx/myapp/app/notifications/consumer.py", line 15, in notification_handler "text": message["text"] File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/channels/generic/websocket.py", line 56, in send {"type": "websocket.send", "text": text_data},
File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/channels/consumer.py", line 107, in send self.base_send(message) File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/asgiref/sync.py", line 64, in __call__ return call_result.result() File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/concurrent/futures/_base.py", line 405, in result return self.__get_result() File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/concurrent/futures/_base.py", line 357, in __get_result raise self._exception File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/asgiref/sync.py", line 78, in main_wrap result = await self.awaitable(*args, **kwargs) File "/Users/muhammed/projects/xxx/lib/python3.6/site-packages/asgiref/server.py", line 71, in application_send raise NotImplementedError("You must implement application_send()") You must implement application_send()
def notification_handler(self, message):
async_to_sync(self.channel_layer.group_send)(
"1", # The group id
{
"text": message["text"]
}
)
print("done")