Как предотвратить ошибку маршрутизации каналов Django?

#python #django #routes #django-channels

Вопрос:

Маршрут для проекта Django Channels, который я создаю, не работает, и на данный момент я не могу сказать, почему. Мне все кажется нормальным, но я снова и снова получаю одну и ту же ошибку от сервера.

Я знаю, что мне чего-то не хватает, но что это может быть?

Настройка ASG

 import os

from channels.routing import ProtocolTypeRouter
from channels.routing import URLRouter
from channels.auth import AuthMiddlewareStack
from django.core.asgi import get_asgi_application
from chat import routing

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "base_app.settings")

# Handles routing protocols for Django Channels
application = ProtocolTypeRouter(
    {
        "http": get_asgi_application(),
        # Points root routing to chat/routing.py
        "websocket": AuthMiddlewareStack(URLRouter(routing.websocket_urlpatterns)),
    }
)
 

Маршрут каналов

 # chat/routing.py
from django.urls import re_path, path
from .consumer import ChatConsumer

websocket_urlpatterns = [
    re_path(r"ws/chat/(?P<chat_id>d )/$", ChatConsumer.as_asgi()),
]

 

Каналы потребителя

 # chat/consumer.py
import json

from django.contrib.auth import get_user_model

from channels.generic.websocket import WebsocketConsumer
from asgiref.sync import async_to_sync

from chat.models import Message
from chat.views import last_10_messages

# Instantiate user model
User = get_user_model()


class ChatConsumer(WebsocketConsumer):
    """Chat consumer class process data sent from WebSocket routing"""

    # === Utility === <---------------- Scroll down to see main Channel's methods

    def fetch_messages(self, data):
        """Fetch last messages from database"""
        messages = last_10_messages(data["chatID"])
        serialized_messages = {
            "command": "fetch_messages",
            "messages": self.messages_to_json(messages),
        }

        # Send fetched messages
        self.send_message(message=serialized_messages)

    def new_message(self, data):
        """Stores and new message"""

        author = data["from"]
        author_is_authenticate = User.objects.filter(username=author)[0]

        # Store and return new message
        message = Message.objects.create(
            author=author_is_authenticate, content=data["message"]
        )

        content = {"command": "new_message", "message": self.message_to_json(message)}

        return self.send_chat_message(content)

    def messages_to_json(self, messages):
        results = []
        for message in messages:
            results.append(self.message_to_json(message))
        return results

    def message_to_json(self, message):
        return {
            "id": message.id,
            "author": message.contact.user.username,
            "content": message.content,
            "timestamp": str(message.timestamp),
        }

    # Chat consumer commands
    commands = {"fetch_messages": fetch_messages, "new_message": new_message}

    # === Main ===

    def connect(self):
        self.chat_id = self.scope["url_route"]["kwargs"]["chat_id"]
        self.room_group_name = "chat_%s" % self.chat_id

        # Join room group
        async_to_sync(self.channel_layer.group_add)(
            self.room_group_name, self.channel_name
        )

        self.accept()

    def disconnect(self, close_code):
        # Leave room group
        async_to_sync(self.channel_layer.group_discard)(
            self.room_group_name, self.channel_name
        )

    def receive(self, text_data):
        """Receive message from WebSocket"""

        data = json.loads(text_data)
        self.commands[data["command"]](self, data)

    def send_chat_message(self, message):
        """Send message to room group"""

        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name, {"type": "chat_message", "message": message}
        )

    def send_message(self, message):
        # Send message to WebSocket
        self.send(text_data=json.dumps(message))

    def chat_message(self, event):
        # Receive message from room group

        message = event["message"]

        # Send message to WebSocket
        self.send(text_data=json.dumps(message))

 

Отслеживание ошибок

 Exception inside application: No route found for path ''.
Traceback (most recent call last):
  File "c:projectschattervenvlibsite-packageschannelsstaticfiles.py", line 44, in __call__
    return await self.application(scope, receive, send)
  File "c:projectschattervenvlibsite-packageschannelsrouting.py", line 71, in __call__
    return await application(scope, receive, send)
  File "c:projectschattervenvlibsite-packageschannelssessions.py", line 47, in __call__
    return await self.inner(dict(scope, cookies=cookies), receive, send)
  File "c:projectschattervenvlibsite-packageschannelssessions.py", line 254, in __call__
    return await self.inner(wrapper.scope, receive, wrapper.send)
  File "c:projectschattervenvlibsite-packageschannelsauth.py", line 181, in __call__
    return await super().__call__(scope, receive, send)
  File "c:projectschattervenvlibsite-packageschannelsmiddleware.py", line 26, in __call__
    return await self.inner(scope, receive, send)
  File "c:projectschattervenvlibsite-packageschannelsrouting.py", line 168, in __call__
    raise ValueError("No route found for path %r." % path)
ValueError: No route found for path ''.
WebSocket DISCONNECT / [127.0.0.1:3378]
 

Комментарии:

1. как вы получаете эту ошибку? Сразу после пробежки? или после подключения?

2. @AndreyNelubin Ошибка появляется, когда я запускаю сервер. Я остановил подключение WebSocket от клиента. Я пытаюсь понять, что вызывает ошибку на сервере, прежде чем устанавливать к нему соединение.

3. пожалуйста, предоставьте ROOT_URLCONF и urlpatterns найдите там

Ответ №1:

Попробуйте это:

Сначала импортируйте AllowedHostsOriginValidator класс из channels.security.websocket

 from channels.security.websocket import AllowedHostsOriginValidator
 

затем передайте AuthMiddlewareStack класс AllowedHostsOriginValidator В.

 # Handles routing protocols for Django Channels
application = ProtocolTypeRouter(
    {
        "http": get_asgi_application(),

        # Points root routing to chat/routing.py
        "websocket": AllowedHostsOriginValidator
           AuthMiddlewareStack(
              URLRouter(routing.websocket_urlpatterns)
           )
        ),
    }
)