0
votes

I want my Django app 'popinion1' to communicate via textmessage with a local machine.

pip freeze :

asgi-redis==1.4.3
asgiref==2.3.2
async-timeout==3.0.1
autobahn==18.12.1
channels==2.1.3
daphne==2.2.4
Django==2.1.3
redis==2.10.6
Twisted==18.9.0

When I do "manage.py runserver" there seems to be a connection or at least no errors

However as soon as I refresh the browser in terminal I get:

  • ERROR - ws_protocol - [Failure instance: Traceback: class'ValueError'>: No route found for path 'input/' [lots of lines] ending with: WebSocket DISCONNECT /input/ [127.0.0.1:50506]

with "/input/" being my app. Firefox inspector reports:

Firefox can't establish connection to Server with ws://127.0.0.1:8000

/input/ being my app.

my routing.py is

from django.conf.urls import url
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from channels.security.websocket import AllowedHostsOriginValidator, OriginValidator
from input.consumers import ChatConsumer


print('ChatConsumer: ', ChatConsumer.name)

application = ProtocolTypeRouter({
    'websocket': AllowedHostsOriginValidator(
        AuthMiddlewareStack(
            URLRouter(
                [
                    url(r'^input/(?P<username>[\w.@+-]+)/$', ChatConsumer),
                ]
            )
        )
    )
})

the javascript in the html template:

<script>

    console.log(window.location)
    var loc = window.location
    var wsStart = 'ws://'
    if (loc.protocol == 'https:'){
        wsStart = 'wss://'
    }
    var endpoint = wsStart + loc.host + loc.pathname
    var socket = new WebSocket(endpoint)


    socket.onmessage = function(e){
        console.log("message", e)
    }
    socket.onopen= function(e){
        console.log("open", e)
    }
    socket.onerror= function(e){
        console.log("error", e)
    }
    socket.onclose= function(e){
        console.log("close", e)
    }
</script>

my consumers.py

import asyncio
import json
from django.contrib.auth import get_user_model
from channels.consumer import AsyncConsumer
from channels.db import database_sync_to_async
from .models import Thread, ChatMessage

from asgiref.sync import async_to_sync

class ChatConsumer(AsyncConsumer):
    name = 'ChatConsumer'

    async def websocket_connect(self, event):
        print('connected! ', event)
        await self.send({
            "type": "websocket.accept"
        })

    async def websocket_receive(self, event):
        print('receive! ', event)


    async def websocket_disconnect(self, event):
        print('disconnected! ', event)

CHANNEL_LAYERS in settings.py

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'asgi_redis.core.RedisChannelLayer',
        'CONFIG': {
            'hosts': [('localhost', 6379)],
        },
        #'ROUTING': 'popinion_project.routing.channel_routing',
    }
}

so is it a wrong address in the routing.py? What's also weird is the last import of "ChatConsumer" in routing.py. It's "unresolved reference" but the print statement works.

print('ChatConsumer: ', ChatConsumer.name)

I'm following this tutorial

https://www.youtube.com/watch?v=RVH05S1qab8

I'd be happy to know how to get the websocket to connect. Hopefully provided all necessary information. Thanks in advance

1
Can you provide the full endpoint you connect to from JS? - Ken4scholars
sorry for my ignorance - but what does this mean exactly? - Mister Ieuns
The endpoint of the websocket to which you connect from your frontend. It is supposed to match the regex for this URL url(r'^input/(?P<username>[\w.@+-]+)/$', ChatConsumer), but it doesn't and that is why you're getting the error. Try to print it in the javascript console before connecting. In that way you can verify the enpoint - Ken4scholars
the endpoint looks right "ws://127.0.0.1:8000/input/" And also installing channels_redis and remapping CHANNELS_LAYERS to 'BACKEND': 'channels_redis.core.RedisChannelLayer' seemed to do the trick. Thanks for the hint with the endpoint. - Mister Ieuns
So the issue then was that you were not adding the username part of the url as I had suspected. Good you resolved it. The channel layer should be related to another error - Ken4scholars

1 Answers

1
votes

The solution I used. It had something to do with the use of url.

from django.urls import re_path
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from channels.security.websocket import AllowedHostsOriginValidator, OriginValidator

from chat.consumers import ChatConsumer
    application = ProtocolTypeRouter({
    # Empty for now (http->django views is added by default)
    'websocket': AllowedHostsOriginValidator(
        AuthMiddlewareStack(
            URLRouter(
                [
                    re_path(r"^messages/(?P<username>[\w.@+-]+)", ChatConsumer),
                ]
            )
        )
    )
})