【问题标题】:How to run WebSocket (django-channels) in production Pythonanywhere?如何在生产 Pythonanywhere 中运行 WebSocket(django-channels)?
【发布时间】:2021-01-20 00:50:24
【问题描述】:

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

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

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

谢谢

我使用的代码

我不知道它是否相关,它在开发中也很完美,所以我认为它没有错误

settings.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)],
        },
    },
}

主路由.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),
]

consumers.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>

【问题讨论】:

    标签: django websocket web-hosting django-channels pythonanywhere


    【解决方案1】:

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

    【讨论】:

    • 我知道这不在问题之列,但是...你能推荐我一个支持 WS 的好的 WEB 托管服务吗?即使它不是免费的-但有退款保证-
    • 你可以试试Digital Ocean。
    猜你喜欢
    • 2021-07-24
    • 1970-01-01
    • 2020-08-01
    • 2021-12-06
    • 2018-05-11
    • 2018-12-17
    • 2022-01-12
    • 2021-07-03
    • 2021-05-12
    相关资源
    最近更新 更多