简体   繁体   English

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

[英]How to run WebSocket (django-channels) in production Pythonanywhere?

I created a simple chat app using WebSockets after following the official Django-channels tutorial.在遵循官方 Django-channels 教程之后,我使用 WebSockets 创建了一个简单的聊天应用程序。 However, I can't get it to work in production.但是,我无法让它在生产中工作。 I have done a few google searching to find out a forum in Pythonanywhere saying that they don't support WebSocket, I contacted the team and they told me the same thing.我做了一些谷歌搜索,在 Pythonanywhere 中找到一个论坛说他们不支持 WebSocket,我联系了团队,他们告诉了我同样的事情。 I have done even more google searching and found things related to Daphne server, Nginx, and a few other things I never heard about before.我做了更多的谷歌搜索,找到了与 Daphne 服务器、Nginx 和其他一些我以前从未听说过的东西相关的东西。

As I'm new to Django-channels I'm currently very confused!由于我是 Django 频道的新手,我目前非常困惑! Is there something I can do to make my WebSocket website run normally in Pythonanywhere on production (for free of course) Or I have to delete all of the WebSocket code and replace it with repetitive Http called to check of new messages (With AJAX)?有什么我可以做的让我的 WebSocket 网站在 Pythonanywhere 中正常运行(当然是免费的)或者我必须删除所有的 WebSocket 代码并将其替换为重复的 Http 调用以检查新消息(使用 AJAX)?

And if there is no other solution but to move to repetitive Http calls, is there any other web hosting service that offers free play which includes free SSL certification, the domain name (such as mydomain.servicename.com) instead of random characters, and WebSocket support?如果没有其他解决方案,只能转向重复的 Http 调用,是否还有其他提供免费播放的网络托管服务,其中包括免费 SSL 认证、域名(例如 mydomain.servicename.com)而不是随机字符,以及WebSocket 支持吗?

Thanks谢谢

the code i use我使用的代码

I don't know if it was relevant, also it's working perfect in development so i don't think there is an error in it 我不知道它是否相关,它在开发中也很完美,所以我认为它没有错误

settings.py:设置.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,
        )
    )
})

main routing.py (in route folder)主路由.py(在路由文件夹中)

from django.urls import path
from . import consumers

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

routing.py for chat app聊天应用的routing.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))

consumers.py消费者.py

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

full js script完整的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>

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM