Невозможно получить данные модели в Django Async conusmers . работая в каналах и вебсокетах

Я работаю над приложением для чата с каналами и вебсокетами, используя асинхронное программирование. Я не могу получить данные модели / объект в consumers.py, но могу создать один .

Когда кто-то из группы отправляет сообщение, оно передается эхом всей группе, но не сохраняется и, таким образом, сбрасывается после обновления страницы. Я хочу сохранить сообщение в базе данных, так как сообщение отправляется группе с помощью websockets. Но я столкнулся с проблемой.

Это мой consumers.py

import json
from channels.generic.websocket import AsyncWebsocketConsumer
from asgiref.sync import sync_to_async
from django.contrib.auth.models import User
from chat.models import ChatMessage , ChatRoom
from channels.db import database_sync_to_async

class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.roomId = self.scope['url_route']['kwargs']['roomId']
        self.room_group_name = 'chat_group_%s' % self.roomId
        
        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )
        
        await self.accept()
        
    async def disconnect(self , close_code):
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )
        
    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message  = text_data_json["message"] 
        username = text_data_json["username"]
        roomId = text_data_json["roomId"]
        roomName = text_data_json["roomName"]
        
        await self.save_message(message , username , roomId , roomName)
        
        
        
        await self.channel_layer.group_send( 
            self.room_group_name,
            {
                'type': 'the_message',
                'message': message
            }
        )
        
    async def the_message(self, event):
        message = event['message']
        await self.send(text_data=json.dumps({
            'message': message
        }))
    
    @sync_to_async    
    def save_message(self , message , username , roomId , roomName) : 
        user = User.objects.get(username = username)
        the_room = ChatRoom.objects.get(roomname = roomName , id = roomId)
        
        new_message = ChatMessage(user = user , chatroom = the_room , message = message )
        new_message.save()
        

Это мой models.py

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

class ChatRoom(models.Model) : 
    host = models.ForeignKey(User , on_delete = models.CASCADE)
    roomname = models.CharField(max_length = 100 , blank = False , null = False)
    participants = models.ManyToManyField(User , verbose_name = "participants" , related_name = "participants")
    created = models.DateTimeField(auto_now_add = True)
    updated = models.DateTimeField(auto_now = True)
    
    
    class Meta: 
        ordering = ["-updated" , "-created"] 

    def __str__(self) : 
        return str(self.host) + " created " + str(self.roomname)
    

class ChatMessage(models.Model) : 
    user = models.ForeignKey(User , on_delete = models.CASCADE)
    chatroom = models.ForeignKey(ChatRoom , on_delete = models.CASCADE)
    message = models.CharField(max_length = 200 )
    created_timestamp = models.DateTimeField(auto_now = True)
    updated_timestamp = models.DateTimeField(auto_now_add = True)
    
    class Meta : 
        ordering = ["-created_timestamp"]
        
    def __str__(self) : 
        return str(self.writer) + " commented " + str(self.message)[:10]

когда я запускаю это, я получаю следующую ошибку .

raise self.model.DoesNotExist(
django.contrib.auth.models.User.DoesNotExist: User matching query does not exist.
WebSocket DISCONNECT /ws/chat/12/ [127.0.0.1:54543]

Пробую другие варианты :

Печать только пользователя с этим битом кода и комментированием метода save_mesage .

async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message  = text_data_json["message"] 
        username = text_data_json["username"]
        roomId = text_data_json["roomId"]
        roomName = text_data_json["roomName"]
        
        
        user = User.objects.get(username = username)
        print(user)

Я получаю эту ошибку ->

raise SynchronousOnlyOperation(message)
django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.

ну это совершенно нормально, что я не могу использовать синхронные методы для получения данных в асинхронных программах .

но когда я пробую это ->

user = await  User.objects.get(username = username)
        print(user)

Я получаю ту же ошибку, что и выше .

Опять пробую другие способы
вот так

user = await database_sync_to_async(User.objects.get(username = username))()
        print(user)

Я получаю ту же ошибку .

снова пытаюсь это сделать ->

user = await sync_to_async(User.objects.get(username = username))()
        print(user)

возникает та же ошибка .

Теперь я попытался получить доступ к данным модели пользователя из функции save_message следующим образом ->

@sync_to_async    
    def save_message(self , message , username , roomId , roomName) : 
        user = database_sync_to_async(User.objects.get(username = username))()
        print(user)

Я получаю эту ошибку ->

raise self.model.DoesNotExist(
django.contrib.auth.models.User.DoesNotExist: User matching query does not exist.
WebSocket DISCONNECT /ws/chat/12/ [127.0.0.1:58689]

Ну, говоря о том, существует пользователь или нет, я являюсь текущим зарегистрированным пользователем в приложении, и я только передаю сообщения. Так что нет никаких сомнений, что пользователь не существует .

Также попробуйте этот способ ->

user = await User.objects.get(username = username)
        await print(user)

это ошибка ->

raise SynchronousOnlyOperation(message)
django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.
WebSocket DISCONNECT /ws/chat/12/ [127.0.0.1:65524]

Вот весь журнал ошибок ->

Я перепробовал все возможные комбинации, как действительные, так и нет, но не смог получить запущенную программу. Пожалуйста, помогите мне. Я застрял на несколько дней. Через день будет неделя.

Любая помощь была бы замечательной. Спасибо

На самом деле в программе не было никакой проблемы. Проблема была в типе возвращаемых данных для json данных через websockets. Когда сообщение было отправлено через websockets, оно было отправлено в форме json данных, а пара ключ-значение имела строковый тип. Таким образом, когда данные были отправлены, дополнительные кавычки также были учтены, и данные вместо того, чтобы быть просто именем пользователя типа string, были фактически в форме строки с дополнительными кавычками в конце. Например -> Имя пользователя текущего пользователя xyz123, тогда оно отправлялось в виде "xyz123". Решением было просто усечь последние две кавычки, что мы и сделали .

Вот рабочий код.

@sync_to_async
    def save_message(self , message , username, roomId , roomName ) :
        username = username[1:-1]
        roomName = roomName[1:-1]
        user = User.objects.get(username = str(username))
        room = ChatRoom.objects.get(roomname =  roomName, id = int(roomId))   
        message = ChatMessage(user = user , chatroom = room , message = str(message))
        message.save()
        print(message)

Вернуться на верх