Django异步嵌套模型加载

1 投票
1 回答
22 浏览
提问于 2025-04-14 16:44

我有一些模型:

class ObjectA(models.Model):
    alias = models.CharField(max_length=50)
    objectb = models.ForeignKey(ObjectB, on_delete=models.PROTECT)

    class Meta:
        db_table = "objecta"

class ObjectB(models.Model):
    name = models.CharField(max_length=50)
    objectc = models.ForeignKey(ObjectC, on_delete=models.PROTECT)

    class Meta:
        db_table = "objectb"

class ObjectC(models.Model):
    name = models.CharField(max_length=50)

    class Meta:
        db_table = "objectc"

在我的 ViewSet 函数里,我想先获取 ObjectA,然后从关联的 ObjectC 中获取名字。

在同步的 Django 中,我会这样做:

get_object_or_404(ObjectA, alias="My alias").objectb.objectc.name

但是在异步的 Django 中,这样做会报错:

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

我找到了一种解决方案,但我觉得这看起来不是很干净:

from django.db.models.query import aprefetch_related_objects
from django.shortcuts import get_object_or_404

get_objecta_model = sync_to_async(get_object_or_404, thread_sensitive=True)
objecta = await get_objecta_model(ObjectA, name=alias)

await aprefetch_related_objects([objecta], "objectb__objectc")

objecta.objectb.objectc.name

1 个回答

1

根据我所了解,这是一种你现在可以使用的解决办法。在异步模式下,不支持延迟查找。

另一种方法是使用明确的 .aget.select_related,而不是使用 get_object_or_404 这个辅助工具:

try:
    objecta = await ObjectA.objects.select_related("objectb__objectc").aget(name="foo")
    objectc_name = objecta.objectb.objectc.name
except ObjectA.DoesNotFound:
    return HttpResponseNotFound()

撰写回答