【发布时间】:2021-03-11 23:56:54
【问题描述】:
我正在尝试获取个人资料的名字,但它给了我这个错误
File "/home/marwan/Desktop/Gowd/venv/lib/python3.6/site-packages/django/utils/asyncio.py", line 24, in inner
raise SynchronousOnlyOperation(message)
django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.
WebSocket DISCONNECT /public_chat/1/ [127.0.0.1:53742]
INFO 2021-03-12 01:43:30,570 runserver 119412 140507688003328 WebSocket DISCONNECT /public_chat/1/ [127.0.0.1:53742]
我认为此错误与尝试在第 56 行获取用户配置文件有关
"profile": self.scope["user"].profile.firstname,
如果我删除它会正常工作
这是我的 consumer.py 文件
from channels.generic.websocket import AsyncJsonWebsocketConsumer
import json
from django.contrib.auth import get_user_model
from gowd_project.users.models import User, Profile
User = get_user_model()
# Example taken from:
# https://github.com/andrewgodwin/channels-examples/blob/master/multichat/chat/consumers.py
class PublicChatConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
"""
Called when the websocket is handshaking as part of initial connection.
"""
print("PublicChatConsumer: connect: " + str(self.scope["user"]))
# let everyone connect. But limit read/write to authenticated users
await self.accept()
# Add them to the group so they get room messages
await self.channel_layer.group_add(
"public_chatroom_1",
self.channel_name,
)
async def disconnect(self, code):
"""
Called when the WebSocket closes for any reason.
"""
# leave the room
print("PublicChatConsumer: disconnect")
pass
async def receive_json(self, content):
"""
Called when we get a text frame. Channels will JSON-decode the payload
for us and pass it as the first argument.
"""
# Messages will have a "command" key we can switch on
command = content.get("command", None)
print("PublicChatConsumer: receive_json: " + str(command))
print("PublicChatConsumer: receive_json: message: " + str(content["message"]))
if command == "send":
if len(content["message"].lstrip()) == 0:
raise Exception("You can't send an empty message.")
await self.send_message(content["message"])
async def send_message(self, message):
await self.channel_layer.group_send(
"public_chatroom_1",
{
"type": "chat.message",
"user_id": self.scope["user"].id,
"user_name": self.scope["user"].name,
"profile": self.scope["user"].profile.firstname,
"message": message,
}
)
async def chat_message(self, event):
"""
Called when someone has messaged our chat.
"""
# Send a message down to the client
print("PublicChatConsumer: chat_message from user #" + str(event["user_id"]))
await self.send_json(
{
"user_id": event["user_id"],
"user_name": event["user_name"],
"message": event["message"],
},
)
【问题讨论】:
-
这是 full 堆栈跟踪吗?如果删除该行使其正常工作,那么错误很清楚地表明您正在尝试那里的东西——我猜数据库调用来获取配置文件对象——在异步方法中是不允许的。我不知道
self.scope["user"]是如何被填充的,但如果您可以控制它,使用select_related与用户一起获取配置文件数据可能会解决您的问题。此外,如果您要重置它,则不应导入用户。 -
我认为这是正确的,它不允许在异步方法中,所以你建议我在这种情况下谁可以获取用户配置文件?你能更清楚一点吗,因为我对这些东西不熟悉
-
错误消息建议您“使用线程或sync_to_async”来解决这个问题。您应该对此进行调查并查看在我的第一条评论中链接的
select_related,看看其中任何一个是否适合您。我不知道哪种方法(如果有的话)适合您的情况,因此您需要根据自己的要求进行研究。
标签: django websocket chat django-channels