django - 如何在生产 Pythonanywhere 中运行 WebSocket (django-channels)?

标签 django websocket web-hosting django-channels pythonanywhere

在遵循官方 Django channel 教程后,我使用 WebSockets 创建了一个简单的聊天应用程序。但是,我无法让它在生产中工作。我做了一些谷歌搜索,发现 Pythonanywhere 的一个论坛说他们不支持 WebSocket,我联系了团队,他们告诉了我同样的事情。 我做了更多的谷歌搜索,发现了与 Daphne 服务器、Nginx 相关的东西,以及其他一些我以前从未听说过的东西。

由于我是 Django channel 的新手,我目前非常困惑!我可以做些什么来使我的 WebSocket 网站在生产环境中的 Pythonanywhere 中正常运行(当然免费),或者我必须删除所有 WebSocket 代码并将其替换为调用以检查新消息的重复 Http(使用 AJAX)?

如果没有其他解决方案,只能转向重复的 Http 调用,是否有任何其他网络托管服务提供免费服务,包括免费 SSL 认证、域名(例如 mydomain.servicename.com)而不是随机的字符和 WebSocket 支持?

谢谢

我使用的代码

我不知道它是否相关,而且它在开发中运行得很好,所以我不认为它有错误

设置.py:

INSTALLED_APPS = [
    'channels',
    ...
    'django_cleanup',
]

ASGI_APPLICATION = 'orgachat.routing.application'

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

主routing.py(在路由文件夹中)

from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from chat.routing import websocket_urlpatterns as chat_routing

application = ProtocolTypeRouter({
    "websocket": AuthMiddlewareStack(
        URLRouter(
            chat_routing,
        )
    )
})

用于聊天应用程序的routing.py

from django.urls import path
from . import consumers

websocket_urlpatterns = [
    path('ws/chat/room/<int:room_id>/', consumers.RoomConsumer),
]

消费者.py

import json
from channels.generic.websocket import AsyncWebsocketConsumer


class RoomConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.group_name = str(self.scope['url_route']['kwargs']['room_id'])
        await self.channel_layer.group_add(self.group_name, self.channel_name)
        await self.accept()

    async def disconnect(self, code):
        await self.channel_layer.group_discard(self.group_name, self.channel_layer)

    async def receive(self, text_data):
        message_json = json.loads(text_data)
        await self.channel_layer.group_send(self.group_name, {
            'type': 'send_message',
            'content': message_json['content'],
            'area': message_json['area'],
            'area_id': message_json['area_id'],
            'username': self.scope['user'].username,

        })

    async def send_message(self, event):
        await self.send(json.dumps(event))

完整的js脚本

<script>
        // -------------------
        // WEBSOCKET SETUP
        // -------------------
        var wsStart = 'ws://'
        var hostName = window.location.hostname + ':8000'
        if (window.location.protocol.includes('https')) {
            wsStart = 'wss://'
            hostName = window.location.hostname
        };
        let endpoint = wsStart + hostName + '/ws' + window.location.pathname
        console.log(endpoint)
        var socket = new WebSocket(endpoint);

        socket.onmessage = function (e) {
            // todo not show message if in a different room
            data = JSON.parse(e.data);
            console.log(data.area_id)
            console.log(data.area)
            var sender = 'other'
            var username = data.username
            if (data.username == "{{ user.username }}") {
                sender = 'self';
                username = 'You'
            }
            document.querySelector('.messages').innerHTML += `
            <div class="message ${sender}">
            <p>${username} &mdash; ${data.area}:</p>
            <p>${data.content}</p>
        </div>
            `
            document.querySelector('#notification_sound').play()
        }
        socket.onerror = function (e) {
            alert("SERVER ERROR 500, You won't be able to see messages unless you refresh,")
        }
        socket.onclose = function (e) {}

        document.addEventListener('DOMContentLoaded', function () {
            document.querySelector('#sendMessage').onclick = function (e) {
                e.preventDefault();
                // ------------AJAX: SEND AND MESSAGE---------------
                let xhr = new XMLHttpRequest();
                xhr.onreadystatechange = function (e) {
                    if (this.readyState == 4 && this.status == 200) {
                        document.querySelector('#id_content').value = '';
                    }
                }
                xhr.open("POST", "{% url 'chat:room' room.id %}", true);
                xhr.setRequestHeader('Content-type', "application/x-www-form-urlencoded");
                data = {
                    'csrfmiddlewaretoken': '{{ csrf_token }}',
                    'content': document.querySelector('#id_content').value,
                    'area': parseInt(document.querySelector('#id_area').value),
                }
                xhr.send(JSON.stringify(data));

                // ---------------WEBSOCKET: ECHO MESSAGE---------------
                let area = document.getElementById('id_area')
                socket.send(JSON.stringify({
                    'content': document.querySelector('#id_content').value,
                    'area': area.options[area.selectedIndex].text,
                    'area_id': document.querySelector('#id_area').value
                }));
            }
        });
    </script>

最佳答案

Websockets,因此,PythonAnywhere 不支持 django-channels。

关于django - 如何在生产 Pythonanywhere 中运行 WebSocket (django-channels)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64203807/

相关文章:

php - 如何在我的网站上显示我的Facebook Wall

java - 使用 Undertow WebSockets 高效发送大数据集

css - Cloudflare 指向我的网站,但 Css 不工作

android - 拥有 godaddy 的网络主机,但用户端有 Squarespace 运行

mysql - MySQL 上嵌套原子 block 和并发进程的 Django 事务失败

python - 是否可以减少样板函数上的参数数量?

android - 套接字在android中连接后立即断开连接

java - http 请求在已部署的 Spring Boot 应用程序中如何工作?

django - 如何使用 trans block 在 jinja2 中标记要翻译的字符串

javascript - 如何在canvas html5中渲染Socket数据?