Django Cookiecutter Channels3 - 连接打开,不发送

发布于 01-19 02:43 字数 6202 浏览 2 评论 0原文

我使用 Django Cookiecutter w/ Docker 启动了一个项目:https://cookiecutter-django.readthedocs。 io/en/latest/

我正在尝试添加频道并按照其文档中的教程进行操作:https://channels.readthedocs.io/en/stable/tutorial

我添加了 Channels 3.0。 4. 到requirements.txt,重建docker容器。

我向settings/base.py添加了频道,这是:

WSGI_APPLICATION = "config.wsgi.application"
ASGI_APPLICATION = "config.asgi.application"

我更新了我的config/asgi.py文件:

import os
import sys
from pathlib import Path

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

ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent
sys.path.append(str(ROOT_DIR / "the_pub"))

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local")

django_application = get_asgi_application()

from config.websocket import websocket_application  # noqa isort:skip

application = ProtocolTypeRouter({
    "https": django_application,
    "websocket": AuthMiddlewareStack(
        URLRouter(
            routing.websocket_urlpatterns
        )
    ),
})

async def application(scope, receive, send):
    if scope["type"] == "http":
        await django_application(scope, receive, send)
    elif scope["type"] == "websocket":
        await websocket_application(scope, receive, send)
    else:
        raise NotImplementedError(f"Unknown scope type {scope['type']}")

创建了一个config/websocket.io文件

async def websocket_application(scope, receive, send):
    while True:
        event = await receive()

        if event["type"] == "websocket.connect":
            await send({"type": "websocket.accept"})

        if event["type"] == "websocket.disconnect":
            break

        if event["type"] == "websocket.receive":
            if event["text"] == "ping":
                await send({"type": "websocket.send", "text": "pong!"})

视图:

# chat/views.py
from django.shortcuts import render

def index(request):
    return render(request, 'chat/index.html')
  
def index(request):
    return render(request, 'chat/index.html', {})

def room(request, room_name):
    return render(request, 'chat/room.html', {
        'room_name': room_name
    })

路由:

# chat/routing.py
from django.urls import re_path
from the_pub.chat import consumers

websocket_urlpatterns = [
    re_path(r'ws/chat/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
]

聊天/网址:

# chat/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('<str:room_name>/', views.room, name='room'),
]

消费者:

# chat/consumers.py
import json
from channels.generic.websocket import WebsocketConsumer

class ChatConsumer(WebsocketConsumer):
    def connect(self):
        self.accept()

    def disconnect(self, close_code):
        pass

    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']

        self.send(text_data=json.dumps({
            'message': message
        }))

app.py

from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _


class ChatConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'the_pub.chat'
    verbose_name= _("Chat")

    def ready(self):
        try:
            import the_pub.users.signals  # noqa F401
        except ImportError:
            pass

模板:

<!-- chat/templates/chat/room.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Chat Room</title>
</head>
<body>
    <textarea id="chat-log" cols="100" rows="20"></textarea><br>
    <input id="chat-message-input" type="text" size="100"><br>
    <input id="chat-message-submit" type="button" value="Send">
    {{ room_name|json_script:"room-name" }}
    <script>
        const roomName = JSON.parse(document.getElementById('room-name').textContent);

        const chatSocket = new WebSocket(
            'ws://'
            + window.location.host
            + '/ws/chat/'
            + roomName
            + '/'
        );

        chatSocket.onmessage = function(e) {
            const data = JSON.parse(e.data);
            document.querySelector('#chat-log').value += (data.message + '\n');
            console.log(data);
        };

        chatSocket.onclose = function(e) {
            console.error('Chat socket closed unexpectedly');
        };

        document.querySelector('#chat-message-input').focus();
        document.querySelector('#chat-message-input').onkeyup = function(e) {
            if (e.keyCode === 13) {  // enter, return
                document.querySelector('#chat-message-submit').click();
            }
        };

        document.querySelector('#chat-message-submit').onclick = function(e) {
            const messageInputDom = document.querySelector('#chat-message-input');
            const message = messageInputDom.value;
            chatSocket.send(JSON.stringify({
                'message': message
            }));
            messageInputDom.value = '';
        };
    </script>
</body>
</html>

当我测试我可以在 Chrome 插件中使用 websocket 发送消息并记录日志。当我点击表单上的“发送”时,它什么也没做。没有控制台警报,docker 日志中没有任何内容。它所做的只是清除文本框中的文本。我不认为第三方可以检查套接字,因为我将其包装在身份验证层中,但事实恰恰相反,我的应用程序的行为就像将消息发送到套接字的 JavaScript 不存在一样。

当您安装 Channels 时,它会提示执行“pip -m install -U Channels”。我向requirements.txt 基本文件添加了通道,并让django cookiecutter 与其余库一起运行安装。这打破了吗?

另外,我正在运行这个项目,它是由 cookiecutter 设置的,我猜是 wsgi。是否可以像这样同时使用 wsgi 和 asgi,或者我应该考虑如何在 asgi 上运行整个网站?

我在控制台中收到错误“DevTools 无法加载源映射:无法加载 /requestProvider.js.map 的内容。我通常会忽略这些错误,但这与触发 .onmessage 时的 socket.send() 函数可疑相关。

I started a a project with Django Cookiecutter w/ Docker: https://cookiecutter-django.readthedocs.io/en/latest/

I'm trying to add Channels and follow the tutorial in their docs: https://channels.readthedocs.io/en/stable/tutorial

I added Channels 3.0.4 to requirements.txt, rebuilt the docker container.

I added channels to settings/base.py, and this:

WSGI_APPLICATION = "config.wsgi.application"
ASGI_APPLICATION = "config.asgi.application"

I updated my config/asgi.py file:

import os
import sys
from pathlib import Path

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

ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent
sys.path.append(str(ROOT_DIR / "the_pub"))

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local")

django_application = get_asgi_application()

from config.websocket import websocket_application  # noqa isort:skip

application = ProtocolTypeRouter({
    "https": django_application,
    "websocket": AuthMiddlewareStack(
        URLRouter(
            routing.websocket_urlpatterns
        )
    ),
})

async def application(scope, receive, send):
    if scope["type"] == "http":
        await django_application(scope, receive, send)
    elif scope["type"] == "websocket":
        await websocket_application(scope, receive, send)
    else:
        raise NotImplementedError(f"Unknown scope type {scope['type']}")

created a config/websocket.io file

async def websocket_application(scope, receive, send):
    while True:
        event = await receive()

        if event["type"] == "websocket.connect":
            await send({"type": "websocket.accept"})

        if event["type"] == "websocket.disconnect":
            break

        if event["type"] == "websocket.receive":
            if event["text"] == "ping":
                await send({"type": "websocket.send", "text": "pong!"})

views:

# chat/views.py
from django.shortcuts import render

def index(request):
    return render(request, 'chat/index.html')
  
def index(request):
    return render(request, 'chat/index.html', {})

def room(request, room_name):
    return render(request, 'chat/room.html', {
        'room_name': room_name
    })

routing:

# chat/routing.py
from django.urls import re_path
from the_pub.chat import consumers

websocket_urlpatterns = [
    re_path(r'ws/chat/(?P<room_name>\w+)/

chat/urls:

# chat/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('<str:room_name>/', views.room, name='room'),
]

consumer:

# chat/consumers.py
import json
from channels.generic.websocket import WebsocketConsumer

class ChatConsumer(WebsocketConsumer):
    def connect(self):
        self.accept()

    def disconnect(self, close_code):
        pass

    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']

        self.send(text_data=json.dumps({
            'message': message
        }))

app.py

from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _


class ChatConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'the_pub.chat'
    verbose_name= _("Chat")

    def ready(self):
        try:
            import the_pub.users.signals  # noqa F401
        except ImportError:
            pass

template:

<!-- chat/templates/chat/room.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Chat Room</title>
</head>
<body>
    <textarea id="chat-log" cols="100" rows="20"></textarea><br>
    <input id="chat-message-input" type="text" size="100"><br>
    <input id="chat-message-submit" type="button" value="Send">
    {{ room_name|json_script:"room-name" }}
    <script>
        const roomName = JSON.parse(document.getElementById('room-name').textContent);

        const chatSocket = new WebSocket(
            'ws://'
            + window.location.host
            + '/ws/chat/'
            + roomName
            + '/'
        );

        chatSocket.onmessage = function(e) {
            const data = JSON.parse(e.data);
            document.querySelector('#chat-log').value += (data.message + '\n');
            console.log(data);
        };

        chatSocket.onclose = function(e) {
            console.error('Chat socket closed unexpectedly');
        };

        document.querySelector('#chat-message-input').focus();
        document.querySelector('#chat-message-input').onkeyup = function(e) {
            if (e.keyCode === 13) {  // enter, return
                document.querySelector('#chat-message-submit').click();
            }
        };

        document.querySelector('#chat-message-submit').onclick = function(e) {
            const messageInputDom = document.querySelector('#chat-message-input');
            const message = messageInputDom.value;
            chatSocket.send(JSON.stringify({
                'message': message
            }));
            messageInputDom.value = '';
        };
    </script>
</body>
</html>

When I test the websocket in a chrome plugin I can send messages and it logs. When I hit send on the form it does nothing. no console alerts, nothing in docker logs. All it does is clear the text in the text box. I didn't think a third party could check the socket because I wrapped it in an authentication layer, but it's the opposite, my app acts like the javascript to send the message to the socket doesn't exist.

when you install Channels, it says to do 'pip -m install -U channels'. I added channels to the requirements.txt base file and let django cookiecutter run install with the rest of the libraries. did this break it?

Also, I'm running this project has it was set up by cookiecutter, which I guess is wsgi. Is it even possible to use both wsgi and asgi like this or should I be looking at how to run the whole site on asgi?

I get an error in the console "DevTools failed to load source map: Could not load content for /requestProvider.js.map. I normally ignore these errors but this seams suspiciously related to the socket.send() function on triggering an .onmessage.

, consumers.ChatConsumer.as_asgi()), ]

chat/urls:

consumer:

app.py

template:

When I test the websocket in a chrome plugin I can send messages and it logs. When I hit send on the form it does nothing. no console alerts, nothing in docker logs. All it does is clear the text in the text box. I didn't think a third party could check the socket because I wrapped it in an authentication layer, but it's the opposite, my app acts like the javascript to send the message to the socket doesn't exist.

when you install Channels, it says to do 'pip -m install -U channels'. I added channels to the requirements.txt base file and let django cookiecutter run install with the rest of the libraries. did this break it?

Also, I'm running this project has it was set up by cookiecutter, which I guess is wsgi. Is it even possible to use both wsgi and asgi like this or should I be looking at how to run the whole site on asgi?

I get an error in the console "DevTools failed to load source map: Could not load content for /requestProvider.js.map. I normally ignore these errors but this seams suspiciously related to the socket.send() function on triggering an .onmessage.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

凉世弥音 2025-01-26 02:43:40
  • 您应该从config/asgi.py.py中删除async def应用程序(...),因为您将应用程序定义为上方的变量。

  • 如果使用频道,则不需要config/websocket.py文件,因为您正在处理消费者的WebSocket连接。

  • 确保 Channels_redis 如果您使用REDIS来用于通道层。

  • 您的chat/views.py具有两个索引视图。不确定这是否是故意的,但是当它不起作用时会造成不必要的混乱。

  • You should remove the async def application(...) from config/asgi.py since you are defining the application as a variable right above.

  • If using channels, the config/websocket.py file is not exactly needed, since you're handling websocket connections from consumers.

  • Make sure channels_redis is installed if you're using Redis for the channel layer.

  • Your chat/views.py has two index views. Not sure if that's intended, but it will create unnecessary confusion when it doesn't work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文