我正在开发一个使用分层数据结构的应用django-rest-framework
程序django-treebeard
。我的(简化的)主要模型看起来像这样
class Task(MP_Node):
name = models.CharField(_('name'), max_length=64)
started = models.BooleanField(default=True)
我目前正在尝试实现的是所有根节点的列表视图,其中显示了额外的字段(例如是否所有子节点都已启动)。为此,我指定了一个视图:
class TaskViewSet(viewsets.ViewSet):
def retrieve(self, request, pk=None):
queryset = Task.get_tree().filter(depth=1, job__isnull=True)
operation = get_object_or_404(queryset, pk=pk)
serializer = TaskSerializer(operation)
return Response(serializer.data)
和序列化器
class TaskSerializer(serializers.ModelSerializer):
are_children_started = serializers.SerializerMethodField()
def get_are_children_started(self, obj):
return all(task.started for task in Task.get_tree(obj))
这一切都有效,我得到了预期的结果。但是,我遇到了 N+1 查询问题,对于每个根任务,我需要分别获取所有子任务。通常这可以使用解决,prefetch_related
但由于我使用物化路径结构django-treebeard
,因此任务模型之间没有 Django 关系,所以prefetch_related
不知道开箱即用。我尝试使用自定义 Prefetch 对象,但由于这仍然需要 Django 关系路径,我无法让它工作。
我目前的想法是使用指向其根节点的外键扩展任务模型,如下所示:
root_node = models.ForeignKey('self', null=True,
related_name='descendant_tasks',
verbose_name=_('root task')
)
为了使 MP 关系明确,以便可以查询。然而,这确实感觉有点像一种不干的方法,所以我想知道是否有人对如何解决它有其他建议。