[Python] Can't establish connection between web socket and server

Discussão em 'Python' iniciado por Stack, Abril 9, 2025.

  1. Stack

    Stack Membro Participativo

    I'm writing a chat app using django channels, redis and daphne. When I try to submit the message and tap on the button I have GET query, but I've written js in my html file and it has to prevent standart behaviour of this form. I don't know why doesn't it establish the connection and just send GET query, what's wrong here? I've checked redis server, It works. I've installed all required modules, I've checked It with gpt, nothing helps. How to make it establish the connection?

    consumer.py:

    import json

    from channels.generic.websocket import AsyncWebsocketConsumer
    from channels.db import database_sync_to_async

    from django.apps import apps

    class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
    self.chat_name = self.scope['url_route']['kwargs']['chat_name']
    await self.channel_layer.group_add(self.chat_name, self.channel_name)

    await self.accept()

    @database_sync_to_async
    def save_message(self, text_data):
    Chat = apps.get_model('chat', 'Chat')
    ChatMessage = apps.get_model('chat', 'ChatMessage')
    User = apps.get_model('auth', 'User')

    chat = Chat.objects.get(chat_name=text_data['chat_name'])
    sender = User.objects.get(username=text_data['sender'])
    ChatMessage.objects.create(
    chat=chat,
    body=text_data['message'],
    sender = sender,
    )

    async def receive(self, text_data):
    print('Received from frontend:', text_data)
    data_json = json.loads(text_data)
    await self.save_message(data_json)

    event = {"type": "send_chat_message", "message": data_json}

    await self.channel_layer.group_send(self.chat_name, event)

    async def send_chat_message(self, event):
    await self.send(text_data=json.dumps({"message": event["message"]}))


    chat.html:

    {% extends "base.html" %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chat</title>
    </head>
    <body>
    {% block content %}
    <div class="container">
    <h2>Chat with {{ chat.members.all.0 }}</h2>
    <div class="card">
    <div class="card-body" id="message-container" style="height: 300px; overflow-y: scroll;">
    {% for message in chat_messages %}
    <p><strong>{{ message.sender.username }}</strong>: {{ message.body }}</p>
    {% empty %}
    <p>There are no meassages yet...</p>
    {% endfor %}
    </div>
    </div>
    <form action="" id="message-form" name='message-form'>
    <input name="message-input" id="message-input"></input>
    <button type="submit">Send</button>
    </form>
    </div>

    {% endblock %}


    <script>
    const chat_name = "{{ chat.chat_name }}"
    const socket = new WebSocket(`ws://127.0.0.1:8000/ws/chat/${chat_name}/`) // creatimg ws connection

    // sending the message to the socket
    const message_form = document.getElementById("message-form")
    message_form.addEventListener( // Listener for submit button
    "submit", function (event) {
    event.preventDefault()
    let sent_message = document.getElementById("message-input").value // get the value of the input of the form
    socket.send(
    JSON.stringify({
    message: sent_message,
    chat_name: "{{ chat.chat_name }}",
    sender: "{{ request.user.username }}"

    })
    )
    }
    )

    //Getting the message
    const chats_div = document.getElementById("message-container") // search for container where we will paste the message
    function scrollToBottom() {
    chats_div.scrollTop = chats_div.scrollHeight
    } //???

    //Processing of the message from the server
    socket.addEventListener("message", function(e) {
    const data = JSON.parse(e.data);

    let sender = data.message.sender
    let content = data.message.message

    let msg_body = document.createElement("div")
    let msg_sender = document.createElement("div")

    msg_body.textContent = content
    msg_sender.textContent = sender

    let chats_div = document.getElementById("message-container")
    let msg = document.createElement("p")
    msg.innerHTML = `<strong>${msg_sender.textContent}</strong>: ${msg_body.textContent}`;

    chats_div.appendChild(msg);
    scrollToBottom()
    })
    </script>

    </body>
    </html>


    asgi.py:

    import os
    import django

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

    from chat.routing import websocket_urlpatterns

    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'messanger.settings')
    django.setup()

    application = ProtocolTypeRouter({
    "http": get_asgi_application(), # Обычные HTTP-запросы
    "websocket": AuthMiddlewareStack(URLRouter(websocket_urlpatterns)),
    })


    routings.py:

    from django.urls import re_path

    from .consumers import ChatConsumer

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


    views.py

    from django.shortcuts import render

    from .models import *

    def chat_list(req):
    chats = req.user.chats.all()
    print(chats)
    return render(req, 'chat_list.html', {'chats': chats})

    def chat(req, chat_name):
    chat = req.user.chats.get(chat_name=chat_name)
    chat_messages = ChatMessage.objects.filter(chat=chat)
    return render(req, 'chat.html', {'chat_messages': chat_messages, 'chat': chat})


    models.py:

    from django.db import models
    from django.contrib.auth.models import User


    class Chat(models.Model):
    chat_name = models.CharField(max_length=50)
    members = models.ManyToManyField(User, related_name='chats')
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
    return self.chat_name


    class ChatMessage(models.Model):
    body = models.TextField()
    chat = models.ForeignKey(Chat, on_delete=models.CASCADE, related_name='chat')
    sender = models.ForeignKey(User, on_delete=models.CASCADE)
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
    return f"Message by @{self.sender} from the chat '{self.chat.chat_name}'"

    Continue reading...

Compartilhe esta Página