簡體   English   中英

如何在生產 Pythonanywhere 中運行 WebSocket (django-channels)?

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

在遵循官方 Django-channels 教程之后,我使用 WebSockets 創建了一個簡單的聊天應用程序。 但是,我無法讓它在生產中工作。 我做了一些谷歌搜索,在 Pythonanywhere 中找到一個論壇說他們不支持 WebSocket,我聯系了團隊,他們告訴了我同樣的事情。 我做了更多的谷歌搜索,找到了與 Daphne 服務器、Nginx 和其他一些我以前從未聽說過的東西相關的東西。

由於我是 Django 頻道的新手,我目前非常困惑! 有什么我可以做的讓我的 WebSocket 網站在 Pythonanywhere 中正常運行(當然是免費的)或者我必須刪除所有的 WebSocket 代碼並將其替換為重復的 Http 調用以檢查新消息(使用 AJAX)?

如果沒有其他解決方案,只能轉向重復的 Http 調用,是否還有其他提供免費播放的網絡托管服務,其中包括免費 SSL 認證、域名(例如 mydomain.servicename.com)而不是隨機字符,以及WebSocket 支持嗎?

謝謝

我使用的代碼

我不知道它是否相關,它在開發中也很完美,所以我認為它沒有錯誤

設置.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,
        )
    )
})

主路由.py(在路由文件夾中)

from django.urls import path
from . import consumers

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

聊天應用的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))

消費者.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>

完整的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