我正在使用Django-Channels消费者来进行websocket异步通信。
我在
下面有这样的内容
class Command(UUIDModel):
owner = models.ForeignKey(AUTH_USER_MODEL, default=None, on_delete=models.SET_DEFAULT, null=True, blank=True, related_name='commands')
name = models.CharField('Name', default='New Command', max_length=128, blank=True, null=True)
class Secret(UUIDModel):
owner = models.ForeignKey(AUTH_USER_MODEL, default=None, on_delete=models.SET_DEFAULT, null=True, blank=True, related_name='secrets')
command = models.ManyToManyField(Command, blank=True, related_name='secrets')
@sync_to_async
def get_command(pk):
command = Command.objects.get(id=pk)
return command
class CommandConsumer(AsyncWebsocketConsumer):
@log_exceptions
async def command(self, event):
log.debug(event)
command = await get_command(event.get('command').get('id'))
log.debug(command)
log.debug(command.secrets)
log.debug(command.secrets.all()) # Fails here
return
我得到一个SynchronousOnlyOperation错误时运行这个,正确的时候,它在manymany字段中评估秘密的查询集。
是否有一种方法可以强制查询集在同步get_command
函数中提前评估,而不是在异步websocket中?这样我就可以很容易地通过command.secrets
访问机密。
目前,我的解决方法是将秘密作为一个单独的变量
来处理。@sync_to_async
def get_command(pk):
command = Command.objects.get(id=pk)
secrets = list(command.secrets.all())
return command, secrets
使用prefetch_related
https://docs.djangoproject.com/en/3.2/ref/models/querysets/#prefetch-related
@sync_to_async
def get_command(pk):
command = Command.objects.prefetch_related("secrets").get(id=pk)
return command
class CommandConsumer(AsyncWebsocketConsumer):
@log_exceptions
async def command(self, event):
log.debug(event)
command = await get_command(event.get('command').get('id'))
log.debug(command)
log.debug(command.secrets)
log.debug(command.secrets.all()) # No longer fails
return