简体   繁体   English

Django 尽早评估多对多关系的查询集以在异步函数中使用

[英]Django Evaluate Queryset of ManyToMany relationship early to use in async function

I'm using a Django-Channels consumer for websocket async communication.我正在使用 Django-Channels 消费者进行 websocket 异步通信。

I have something like this below我在下面有这样的东西


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

I get a SynchronousOnlyOperation error when running this, right when it evaluates the queryset for Secrets in the ManyToMany field.运行此程序时,当它评估 ManyToMany 字段中 Secrets 的查询集时,我得到一个 SynchronousOnlyOperation 错误。

Is there a way to force the queryset to evaluate ahead of time in the synchronous get_command function, instead of in the async websocket?有没有办法强制查询集在同步get_command函数中提前评估,而不是在异步 websocket 中? That way I can easily access the secrets via command.secrets .这样我就可以通过command.secrets轻松访问这些秘密。

Currently, my workaround is to just handle the secrets as a separate variable目前,我的解决方法是将机密作为单独的变量处理

@sync_to_async
def get_command(pk):
    command = Command.objects.get(id=pk)
    secrets = list(command.secrets.all())
    return command, secrets

Use prefetch_related https://docs.djangoproject.com/en/3.2/ref/models/querysets/#prefetch-related使用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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM