Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

django 2.2 implement alongside websockets and i get a AttributeError: module 'django_eventstream.urls' has no attribute 'callback' #106

Open
simkimsia opened this issue Dec 22, 2022 · 2 comments

Comments

@simkimsia
Copy link

simkimsia commented Dec 22, 2022

this is my asgi.py

"""
ASGI entrypoint. Configures Django and then runs the application
defined in the ASGI_APPLICATION setting.
"""
import os

import django
from channels.routing import get_default_application
from django.conf import settings

# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks
# if running multiple sites in the same mod_wsgi process. To fix this, use
# mod_wsgi daemon mode with each site in its own daemon process, or use
# os.environ["DJANGO_SETTINGS_MODULE"] = "config.settings.production"
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")

if not settings.configured:
    # set the default Django settings module for the 'celery' program.
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.local')  # pragma: no cover

django.setup()
application = get_default_application()

this is my routing.py

import django_eventstream
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.urls import path

from websockets.consumers import WSConsumer

application = ProtocolTypeRouter({
    "websocket": AuthMiddlewareStack(
        URLRouter([
            path("websocket/", WSConsumer),
        ])
    ),
    'http': URLRouter([
        path('events/', AuthMiddlewareStack(
            URLRouter(django_eventstream.routing.urlpatterns)
        ), { 'channels': ['test'] }),
        path('pre_quotations_bulk_create_requests/(?P<pk>\d+)/events/$',
            include(django_eventstream.urls),
            {'format-channels': ['pre_quotations_bulk_create_request-{pk}']}),
    ]),
})

my requirements

celery[redis]==5.2.7 # May 2022 https://github.com/celery/celery
channels==3.0.5  # June 2022 channels 3 work with eventstream and django 2.2 https://github.com/django/channels/releases/tag/3.0.5
channels-redis==3.4.1  # Jul 2022 https://github.com/django/channels_redis/releases/tag/3.4.1
django-eventstream==4.5.0 # Dec 2022 https://github.com/fanout/django-eventstream/releases/tag/4.5.0

What is my objective?

i want to use SSE for

/pre_quotations_bulk_create_requests/(?P<pk>\d+)/events/

What's the issue?

i cannot use include as per the code snippet at https://github.com/fanout/django-eventstream#routes-and-channel-selection

# specify a list of dynamic channels using formatting based on view keywords
path('objects/<obj_id>/events/', include(django_eventstream.urls),
    {'format-channels': ['object-{obj_id}']})

i get a

 File "/app/websockets/routing.py", line 14, in <module>
eno-a3-django-django-1     |     'http': URLRouter([
eno-a3-django-django-1     |   File "/opt/venv/lib/python3.10/site-packages/channels/routing.py", line 129, in __init__
eno-a3-django-django-1     |     raise ImproperlyConfigured(
eno-a3-django-django-1     | django.core.exceptions.ImproperlyConfigured: <URLResolver <module 'django_eventstream.urls' from '/opt/venv/lib/python3.10/site-packages/django_eventstream/urls.py'> (None:None) 'pre_quotations_bulk_create_requests/(?P<pk>\d+)/events/$'>: include() is not supported in URLRouter. Use nested URLRouter instances instead.

so i change to

        path('pre_quotations_bulk_create_requests/(?P<pk>\d+)/events/$',
			URLRouter([django_eventstream.urls])
            {'format-channels': ['pre_quotations_bulk_create_request-{pk}']}),

now i get a

eno-a3-django-django-1     |   File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
eno-a3-django-django-1     |   File "<frozen importlib._bootstrap_external>", line 883, in exec_module
eno-a3-django-django-1     |   File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
eno-a3-django-django-1     |   File "/app/websockets/routing.py", line 19, in <module>
eno-a3-django-django-1     |     URLRouter([django_eventstream.urls]),
eno-a3-django-django-1     |   File "/opt/venv/lib/python3.10/site-packages/channels/routing.py", line 125, in __init__
eno-a3-django-django-1     |     if getattr(route.callback, "_path_routing", False) is True:
eno-a3-django-django-1     | AttributeError: module 'django_eventstream.urls' has no attribute 'callback'
eno-a3-django-mailhog-1    | [APIv1] KEEPALIVE /api/v1/events

What do I do now?

@jowenn
Copy link

jowenn commented Jan 4, 2023

Not tested, but guessing from the documentation is should be:

path('pre_quotations_bulk_create_requests/(?P\d+)/events/$',
URLRouter(django_eventstream.urls.urlpatterns),
{'format-channels': ['pre_quotations_bulk_create_request-{pk}']}),

django_eventstream.urls.urlpatterns is a list of Pathes, and that's what URLRouter expects

@jkarneges
Copy link
Member

Ah, I just realized the examples in the routes section use the style expected by urls.py which only works in WSGI mode.

The examples need to be slightly adjusted for use with ASGI. Namely, the second argument to the path should be URLRouter(django_eventstream.routing.urlpatterns), and that value needs to be wrapped in AuthMiddlewareStack if you want to handle auth.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants