Django Channels 2.0.0 groups

767 views
Skip to first unread message

Ahmed Magdy

unread,
Feb 2, 2018, 7:21:22 AM2/2/18
to Django users
I'm relatively new to channels and was using Channels v1.x.x groups easily, but after v2.0.0 update and reading the documentation

# This example uses WebSocket consumer, which is synchronous, and so
# needs the async channel layer functions to be converted.
from asgiref.sync import AsyncToSync

class ChatConsumer(WebsocketConsumer):

   
def connect(self):
       
AsyncToSync(self.channel_layer.group_add)("chat", self.channel_name)

   
def disconnect(self):
       
AsyncToSync(self.channel_layer.group_discard)("chat", self.channel_name)
Enter code here...

channel_layer, channel_name are always NoneType and exception occurs.

Is that because I didn't configure channel layers? But in the old version I also used the in memory type and Groups were working well.

Andrew Godwin

unread,
Feb 2, 2018, 12:37:36 PM2/2/18
to django...@googlegroups.com
Hi Ahmed,

In the new release channel layers are optional - if you don't configure them they will indeed come through as None. The settings format changed slightly too - you can read more here: http://channels.readthedocs.io/en/latest/topics/channel_layers.html

Andrew

--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/fff84d59-da69-47d5-a7c3-ee0221680642%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Ahmed Magdy

unread,
Feb 2, 2018, 8:17:37 PM2/2/18
to Django users
That's what I did after reading the documentation here's how my channels files look like

# settings.py
# ...
ASGI_APPLICATION = 'djangoChannels.routing.application'
# ...

# routing.py
from django.conf.urls import url

from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack

from .consumers import ChatConsumer

application = ProtocolTypeRouter({
   # Empty for now (http->django views is added by default)
   'websocket': AuthMiddlewareStack(
       URLRouter([
           url('^sessions/$', ChatConsumer)
       ])
   )
})

# consumers.py
from asgiref.sync import AsyncToSync
from channels.generic.websocket import WebsocketConsumer

class ChatConsumer(WebsocketConsumer):

    def connect(self):
       AsyncToSync(self.channel_layer.group_add)("chat", self.channel_name)

    def disconnect(self):
       AsyncToSync(self.channel_layer.group_discard)("chat", self.channel_name)


After connecting with JS websocket to

ws://127.0.0.1:8000/sessions/

Raises an exception

Performing system checks...

System check identified no issues (0 silenced).
February 03, 2018 - 03:14:29
Django version 2.0.2, using settings 'djangoChannels.settings'
Starting ASGI/Channels development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
2018-02-03 03:14:29,799 - INFO - server - HTTP/2 support not enabled (install the http2 and tls Twisted extras)
2018-02-03 03:14:29,800 - INFO - server - Listening on endpoint tcp:port=8000:interface=127.0.0.1
[2018/02/03 03:14:32] WebSocket HANDSHAKING /sessions/ [127.0.0.1:8631]
ERROR:root:Exception inside application: 'NoneType' object has no attribute 'group_add'
  File "c:\python35\Lib\asyncio\tasks.py", line 241, in _step
    result = coro.throw(exc)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels\consumer.py", line 53, in __call__
    await await_many_dispatch([receive], self.dispatch)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels\utils.py", line 48, in await_many_dispatch
    await dispatch(result)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\asgiref\sync.py", line 84, in inner
    return await async_func(*args, **kwargs)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\asgiref\sync.py", line 67, in __call__
    return await asyncio.wait_for(future, timeout=None)
  File "c:\python35\Lib\asyncio\tasks.py", line 367, in wait_for
    return (yield from fut)
  File "c:\python35\Lib\asyncio\futures.py", line 358, in __iter__
    yield self  # This tells Task to wait for completion.
  File "c:\python35\Lib\asyncio\tasks.py", line 290, in _wakeup
    future.result()
  File "c:\python35\Lib\asyncio\futures.py", line 274, in result
    raise self._exception
  File "c:\python35\Lib\concurrent\futures\thread.py", line 55, in run
    result = self.fn(*self.args, **self.kwargs)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\asgiref\sync.py", line 76, in thread_handler
    raise e
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\asgiref\sync.py", line 74, in thread_handler
    self.func(*args, **kwargs)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels\consumer.py", line 93, in dispatch
    handler(message)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels\generic\websocket.py", line 19, in websocket_connect
    self.connect()
  File "D:\Programming\DjangoWebsite\HUWebsite\husite\djangoChannels\djangoChannels\consumers.py", line 8, in connect
    AsyncToSync(self.channel_layer.group_add)("chat", self.channel_name)
  'NoneType' object has no attribute 'group_add'
[2018/02/03 03:14:32] WebSocket DISCONNECT /sessions/ [127.0.0.1:8631]


On Friday, February 2, 2018 at 7:37:36 PM UTC+2, Andrew Godwin wrote:
Hi Ahmed,

In the new release channel layers are optional - if you don't configure them they will indeed come through as None. The settings format changed slightly too - you can read more here: http://channels.readthedocs.io/en/latest/topics/channel_layers.html

Andrew
On Fri, Feb 2, 2018 at 3:31 AM, Ahmed Magdy <ahmed...@gmail.com> wrote:
I'm relatively new to channels and was using Channels v1.x.x groups easily, but after v2.0.0 update and reading the documentation

# This example uses WebSocket consumer, which is synchronous, and so
# needs the async channel layer functions to be converted.
from asgiref.sync import AsyncToSync

class ChatConsumer(WebsocketConsumer):

   
def connect(self):
       
AsyncToSync(self.channel_layer.group_add)("chat", self.channel_name)

   
def disconnect(self):
       
AsyncToSync(self.channel_layer.group_discard)("chat", self.channel_name)
Enter code here...

channel_layer, channel_name are always NoneType and exception occurs.

Is that because I didn't configure channel layers? But in the old version I also used the in memory type and Groups were working well.

--
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...@googlegroups.com.

Andrew Godwin

unread,
Feb 2, 2018, 8:36:43 PM2/2/18
to django...@googlegroups.com
Do you have a CHANNEL_LAYERS setting in your settings file? If so, what is it set to?

Andrew

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.

Ahmed Magdy

unread,
Feb 2, 2018, 11:04:03 PM2/2/18
to Django users
I tried not having CHANNEL_LAYERS or setting it to {}
same exception

Andrew Godwin

unread,
Feb 2, 2018, 11:08:02 PM2/2/18
to django...@googlegroups.com
It needs to contain a value to work - what value were you trying that was not empty?

Andrew

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.

Ahmed Magdy

unread,
Feb 2, 2018, 11:42:47 PM2/2/18
to Django users
I thought it uses in memory channel layer by default if it's empty? I didn't try setting a value, because only redis was available in v2.0.0 and I don't like using stuff I don't understand.

Andrew Godwin

unread,
Feb 2, 2018, 11:47:47 PM2/2/18
to django...@googlegroups.com
No, there is no in-memory channel layer any more, only Redis is available at the moment. You must put something into the settings in order to make it function.

Andrew

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.

Ahmed Magdy

unread,
Feb 2, 2018, 11:52:26 PM2/2/18
to Django users
Aha thanks for making it clear, I will read more about redis then. Shouldn't the docs mention that though?

Andrew Godwin

unread,
Feb 2, 2018, 11:58:56 PM2/2/18
to django...@googlegroups.com
The docs do mention this in a big callout at the top of the Channel Layers page :) http://channels.readthedocs.io/en/latest/topics/channel_layers.html

Andrew

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.

Ahmed Magdy

unread,
Feb 3, 2018, 1:35:30 AM2/3/18
to Django users
I even made sure to read the docs multiple times before posting. :/

I've been reading about Redis, and since I got windows OS, I installed the port for Windows based redis, tested the server and client they are working ok.

# settings.py
# ...
ASGI_APPLICATION = 'djangoChannels.routing.application'

CHANNEL_LAYERS = {
   "default": {
       "BACKEND": "channels_redis.core.RedisChannelLayer",
       "CONFIG": {
           "hosts": [("localhost", 6379)],
       },
   },
}


# consumers.py
from asgiref.sync import AsyncToSync
from channels.generic.websocket import WebsocketConsumer

class ChatConsumer(WebsocketConsumer):
   def connect(self):
       AsyncToSync(self.channel_layer.group_add)("chat", self.channel_name)

    def disconnect(self):
       AsyncToSync(self.channel_layer.group_discard)("chat", self.channel_name)

raises an exception

[2018/02/03 08:30:19] WebSocket HANDSHAKING /sessions/ [127.0.0.1:12778]
ERROR:root:Exception inside application: There is no current event loop in thread 'Thread-3'.

  File "c:\python35\Lib\asyncio\tasks.py", line 241, in _step
    result = coro.throw(exc)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels\consumer.py", line 51, in __call__
    await await_many_dispatch([receive, self.channel_receive], self.dispatch)

  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels\utils.py", line 48, in await_many_dispatch
    await dispatch(result)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\asgiref\sync.py", line 84, in inner
    return await async_func(*args, **kwargs)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\asgiref\sync.py", line 67, in __call__
    return await asyncio.wait_for(future, timeout=None)
  File "c:\python35\Lib\asyncio\tasks.py", line 367, in wait_for
    return (yield from fut)
  File "c:\python35\Lib\asyncio\futures.py", line 358, in __iter__
    yield self  # This tells Task to wait for completion.
  File "c:\python35\Lib\asyncio\tasks.py", line 290, in _wakeup
    future.result()
  File "c:\python35\Lib\asyncio\futures.py", line 274, in result
    raise self._exception
  File "c:\python35\Lib\concurrent\futures\thread.py", line 55, in run
    result = self.fn(*self.args, **self.kwargs)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\asgiref\sync.py", line 76, in thread_handler
    raise e
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\asgiref\sync.py", line 74, in thread_handler
    self.func(*args, **kwargs)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels\consumer.py", line 93, in dispatch
    handler(message)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels\generic\websocket.py", line 19, in websocket_connect
    self.connect()
  File "D:\Programming\DjangoWebsite\HUWebsite\husite\djangoChannels\djangoChannels\consumers.py", line 7, in connect
    AsyncToSync(self.channel_layer.group_add)("chat", self.channel_name)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\asgiref\sync.py", line 17, in __init__
    self.main_event_loop = asyncio.get_event_loop()
  File "c:\python35\Lib\asyncio\events.py", line 626, in get_event_loop
    return get_event_loop_policy().get_event_loop()
  File "c:\python35\Lib\asyncio\events.py", line 572, in get_event_loop
    % threading.current_thread().name)
  There is no current event loop in thread 'Thread-3'.

Thanks for what you did so far!

Andrew Godwin

unread,
Feb 3, 2018, 1:47:01 AM2/3/18
to django...@googlegroups.com
Yup, that looks like a genuine bug, I have opened a GitHub issue to track it: https://github.com/django/channels/issues/848

Andrew

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.

Ahmed Magdy

unread,
Feb 3, 2018, 2:36:10 AM2/3/18
to Django users
Since you closed the issue, I'm posting here.
Ok, so I've updated asgiref package to 2.1.1 and now getting different exception.


[2018/02/03 09:29:23] WebSocket HANDSHAKING /sessions/ [127.0.0.1:13235]
ERROR:root:Exception inside application: '_WindowsSelectorEventLoop' object has no attribute 'create_future'

  File "c:\python35\Lib\asyncio\tasks.py", line 241, in _step
    result = coro.throw(exc)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels\consumer.py", line 51, in __call__
    await await_many_dispatch([receive, self.channel_receive], self.dispatch)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels\utils.py", line 48, in await_many_dispatch
    await dispatch(result)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\asgiref\sync.py", line 99, in inner
    return await async_func(*args, **kwargs)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\asgiref\sync.py", line 79, in __call__

    return await asyncio.wait_for(future, timeout=None)
  File "c:\python35\Lib\asyncio\tasks.py", line 367, in wait_for
    return (yield from fut)
  File "c:\python35\Lib\asyncio\futures.py", line 358, in __iter__
    yield self  # This tells Task to wait for completion.
  File "c:\python35\Lib\asyncio\tasks.py", line 290, in _wakeup
    future.result()
  File "c:\python35\Lib\asyncio\futures.py", line 274, in result
    raise self._exception
  File "c:\python35\Lib\concurrent\futures\thread.py", line 55, in run
    result = self.fn(*self.args, **self.kwargs)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\asgiref\sync.py", line 91, in thread_handler
    raise e
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\asgiref\sync.py", line 89, in thread_handler

    self.func(*args, **kwargs)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels\consumer.py", line 93, in dispatch
    handler(message)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels\generic\websocket.py", line 19, in websocket_connect
    self.connect()
  File "D:\Programming\DjangoWebsite\HUWebsite\husite\djangoChannels\djangoChannels\consumers.py", line 7, in connect
    AsyncToSync(self.channel_layer.group_add)("chat", self.channel_name)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\asgiref\sync.py", line 45, in __call__
    call_result.result()
  File "c:\python35\Lib\concurrent\futures\_base.py", line 405, in result
    return self.__get_result()
  File "c:\python35\Lib\concurrent\futures\_base.py", line 357, in __get_result
    raise self._exception
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\asgiref\sync.py", line 53, in main_wrap
    result = await self.awaitable(*args, **kwargs)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels_redis\core.py", line 280, in group_add
    pool = await self.connection(self.consistent_hash(group))
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels_redis\core.py", line 377, in connection
    self.pools[index] = await aioredis.create_redis_pool(**self.hosts[index])
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\aioredis\commands\__init__.py", line 197, in create_redis_pool
    loop=loop)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\aioredis\pool.py", line 56, in create_pool
    await pool._fill_free(override_min=False)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\aioredis\pool.py", line 388, in _fill_free
    conn = await self._create_new_connection(address)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\aioredis\connection.py", line 124, in create_connection
    loop=loop)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\aioredis\connection.py", line 163, in __init__
    self._close_waiter = loop.create_future()
  '_WindowsSelectorEventLoop' object has no attribute 'create_future'
[2018/02/03 09:29:24] WebSocket DISCONNECT /sessions/ [127.0.0.1:13235]
[2018/02/03 09:30:24] HTTP GET /sessions/ 503 [60.64, 127.0.0.1:13235]
ERROR:asyncio:Task exception was never retrieved
future: <Task finished coro=<receive() done, defined at D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels_redis\core.py:137> exception=AttributeError("'_WindowsSelectorEventLoop'
object has no attribute 'create_future'",)>
Traceback (most recent call last):
  File "c:\python35\Lib\asyncio\tasks.py", line 239, in _step
    result = coro.send(None)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels_redis\core.py", line 158, in receive
    return await self.receive_buffer_lpop(channel)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels_redis\core.py", line 220, in receive_buffer_lpop
    task.result()

  File "c:\python35\Lib\asyncio\futures.py", line 274, in result
    raise self._exception
  File "c:\python35\Lib\asyncio\tasks.py", line 239, in _step
    result = coro.send(None)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels_redis\core.py", line 171, in receive_loop
    real_channel, message = await self.receive_single(channel)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels_redis\core.py", line 187, in receive_single
    pool = await self.connection(index)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\channels_redis\core.py", line 377, in connection
    self.pools[index] = await aioredis.create_redis_pool(**self.hosts[index])
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\aioredis\commands\__init__.py", line 197, in create_redis_pool
    loop=loop)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\aioredis\pool.py", line 56, in create_pool
    await pool._fill_free(override_min=False)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\aioredis\pool.py", line 388, in _fill_free
    conn = await self._create_new_connection(address)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\aioredis\connection.py", line 124, in create_connection
    loop=loop)
  File "D:\Programming\DjangoWebsite\HUWebsite\lib\site-packages\aioredis\connection.py", line 163, in __init__
    self._close_waiter = loop.create_future()
AttributeError: '_WindowsSelectorEventLoop' object has no attribute 'create_future'

Andrew Godwin

unread,
Feb 3, 2018, 2:41:38 AM2/3/18
to django...@googlegroups.com
That looks like a problem with the version of Python you are running - what version is it?

Andrew

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.

Ahmed Magdy

unread,
Feb 3, 2018, 2:44:17 AM2/3/18
to Django users
v3.5.1:37a07cee5969

Andrew Godwin

unread,
Feb 3, 2018, 2:47:04 AM2/3/18
to django...@googlegroups.com
Ah, yes, it looks like aioredis requires at least 3.5.2. I will update the channels_redis readme to make this clear.

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.

Ahmed Magdy

unread,
Feb 3, 2018, 3:19:36 AM2/3/18
to Django users
Finally, I think reverting back to channels 1.x.x was much easier for you and me. ^^
Really appreciate what you did and the project, now I can implement the chatting functionality for my graduation project.
Reply all
Reply to author
Forward
0 new messages