无法获取配置文件对象名字
Posted
技术标签:
【中文标题】无法获取配置文件对象名字【英文标题】:can't get the profile object firstname 【发布时间】: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
,看看其中任何一个是否适合您。我不知道哪种方法(如果有的话)适合您的情况,因此您需要根据自己的要求进行研究。
【参考方案1】:
sync_to_async
接受一个可调用对象,而不是结果。所以,我需要这样做:
@sync_to_async
def get_user_profile(self, user):
return user.profile
async def send_message(self, message):
profile = await PublicChatConsumer.get_user_profile(self.scope["user"])
profile_name = profile.firstname
await self.channel_layer.group_send(
"public_chatroom_1",
"type": "chat.message",
"user_id": self.scope["user"].id,
"username": profile_name,
"message": message,
)
full documentation Similar problem
【讨论】:
以上是关于无法获取配置文件对象名字的主要内容,如果未能解决你的问题,请参考以下文章
IDEA hibernate xml配置文件中表名字段报红,无法通过点击表名跳转到数据库表