pythondjangodjango-rest-frameworkwebsocketdjango-channels

Django Rest Framework + Django Channels -> [Errno 111] Connect call failed ('127.0.0.1', 6379)


I am programming a project with Django (4.2.6), Django Rest Framework (3.14.0), Channels (4.0.0) and Channels-Redis(4.2.0), which acts as a backend for a mobile application. So far, I haven't had any problems with the Rest API connections and the endpoints I developed. I try to test the connection through websockets, but I get the following error:

Exception inside application: Error connecting to localhost:6379. Multiple exceptions: [Errno 111] Connect call failed ('::1', 6379, 0, 0), [Errno 111] Connect call failed ('127.0.0.1', 6379).
Traceback (most recent call last):
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/redis/asyncio/connection.py", line 274, in connect
    await self.retry.call_with_retry(
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/redis/asyncio/retry.py", line 59, in call_with_retry
    return await do()
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/redis/asyncio/connection.py", line 681, in _connect
    reader, writer = await asyncio.open_connection(
  File "/usr/lib/python3.10/asyncio/streams.py", line 48, in open_connection
    transport, _ = await loop.create_connection(
  File "/usr/lib/python3.10/asyncio/base_events.py", line 1084, in create_connection
    raise OSError('Multiple exceptions: {}'.format(
OSError: Multiple exceptions: [Errno 111] Connect call failed ('::1', 6379, 0, 0), [Errno 111] Connect call failed ('127.0.0.1', 6379)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/django/contrib/staticfiles/handlers.py", line 101, in __call__
    return await self.application(scope, receive, send)
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/channels/routing.py", line 62, in __call__
    return await application(scope, receive, send)
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/channels/routing.py", line 116, in __call__
    return await application(
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/channels/consumer.py", line 94, in app
    return await consumer(scope, receive, send)
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/channels/consumer.py", line 58, in __call__
    await await_many_dispatch(
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/channels/utils.py", line 50, in await_many_dispatch
    await dispatch(result)
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/channels/consumer.py", line 73, in dispatch
    await handler(message)
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/djangochannelsrestframework/consumers.py", line 84, in websocket_connect
    await super().websocket_connect(message)
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/channels/generic/websocket.py", line 173, in websocket_connect
    await self.connect()
  File "/home/tecnicus/Documentos/Repositorios/MyProyect/MyApp/api/consumers.py", line 16, in connect
    await self.model_change.subscribe()
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/Selene_Backend_Copy_Test/lib/python3.10/site-packages/djangochannelsrestframework/observer/base_observer.py", line 144, in subscribe
    await consumer.add_group(group_name)
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/djangochannelsrestframework/consumers.py", line 102, in add_group
    await self.channel_layer.group_add(name, self.channel_name)
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/channels_redis/core.py", line 504, in group_add
    await connection.zadd(group_key, {channel: time.time()})
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/redis/asyncio/client.py", line 605, in execute_command
    conn = self.connection or await pool.get_connection(command_name, **options)
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/redis/asyncio/connection.py", line 1076, in get_connection
    await self.ensure_connection(connection)
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/redis/asyncio/connection.py", line 1109, in ensure_connection
    await connection.connect()
  File "/home/tecnicus/Documentos/Repositorios/virtualenvs/virtualenv1/lib/python3.10/site-packages/redis/asyncio/connection.py", line 282, in connect
    raise ConnectionError(self._error_message(e))
redis.exceptions.ConnectionError: Error connecting to localhost:6379. Multiple exceptions: [Errno 111] Connect call failed ('::1', 6379, 0, 0), [Errno 111] Connect call failed ('127.0.0.1', 6379).
WebSocket DISCONNECT /ws/ [127.0.0.1:33284]


As I am a newbie when it comes to the 3 frameworks mentioned, I tried to follow the documentation of them as best I could, plus the tutorials that I found about it.

Settings.py

INSTALLED_APPS = [

    'daphne',

    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    
    'channels',
    'rest_framework',
    'rest_framework_simplejwt',
    'rest_framework_simplejwt.token_blacklist',
    'djangochannelsrestframework',
    'django_cleanup.apps.CleanupConfig',
    'drf_yasg',
    'django_filters',
    'rangefilter',
    
    # Aplicaciones
    'MyApp',

    
]

ASGI_APPLICATION = 'SeleneServer.asgi.application'


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

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
        'rest_framework.authentication.SessionAuthentication'),
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}

SIMPLE_JWT = {
    "ACCESS_TOKEN_LIFETIME": timedelta(hours=12),
    "REFRESH_TOKEN_LIFETIME": timedelta(days=7),
    'UPDATE_LAST_LOGIN': True
}

Asgi.py


import os
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from django.core.asgi import get_asgi_application
import agenda.api.router


os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'SeleneServer.settings')

django_asgi_app = get_asgi_application()

application = ProtocolTypeRouter({
    'http': django_asgi_app,
    'websocket': AuthMiddlewareStack( 
        URLRouter(
            agenda.api.router.websocket_urlpatterns
        )
    )
})

Router.py


from django.urls import re_path
from MyApp.api.consumers import MyConsumer


websocket_urlpatterns = [
    re_path(r"^ws/", MyConsumer.as_asgi()),
]

Consumers.py


from djangochannelsrestframework import permissions
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from djangochannelsrestframework.mixins import ListModelMixin
from djangochannelsrestframework.observer import model_observer

from MyApp.models import MyModel
from MyApp.api.serializers import MyModelSerializer

class MyConsumer(ListModelMixin, GenericAsyncAPIConsumer):

    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer
    permissions = (permissions.AllowAny,)

    async def connect(self, **kwargs):
        await self.model_change.subscribe()
        await super().connect()

    @model_observer(MyModel)
    async def model_change(self, message, observer=None, **kwargs):
        await self.send_json(message)

    @model_change.serializer
    def model_serialize(self, instance, action, **kwargs):
        return dict(data=MyModelSerializer(instance=instance).data, action=action.value)


I am not using docker or anything similar, since I only want the project to work locally on my computer first, before uploading it to the Vercel server.


I tried to try running the project without Daphne, because I heard that for the latest versions of Channels it was not a required dependency, but the result was that when testing the websocket, the server threw an error that the address to which the request was made cannot be found:

Not Found: /ws/      
[05/Mar/2024 02:31:15] "GET /ws/ HTTP/1.1" 404 3003).

I also tried to remove the AuthMiddlewareStack from asgi.py to test a connection that does not require the user to be logged in, but the results are the same, with or without daphne.

I don't know if you recommend another way to check the websocket connection, since I have used Browser WebSocket Client for Chrome, and websocket-client for python, always at ws://127.0.0.1:8000/ws/, since the frontend, which will be developed in React Native and will not be developed yet, but I must test if the websocket system will work, even if it is at a very basic.


Solution

  • Channels need a REDIS backend to be able to operate. You need to install and start REDIS to solve the error