我正在使用django-rest-framework和django-treebeard开发一个具有分层数据结构的应用程序。我的(简化后的)主模型如下:
我正在努力实现的目标是列出所有根节点的列表视图,其中显示额外字段(例如所有子项是否已启动)。为此,我指定了一个视图:
这一切都能正常工作,我也得到了预期的结果。然而,我遇到了一个N+1查询问题,对于每个根任务,我需要单独获取所有子项。通常可以使用
我的当前想法是通过添加指向其根节点的外键来扩展Task模型,如下所示:
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
中的Materialized Path结构,因此任务模型之间没有Django关系,所以prefetch_related
无法直接处理。我尝试使用自定义Prefetch对象,但由于这仍然需要Django关系路径,因此我无法使其正常工作。我的当前想法是通过添加指向其根节点的外键来扩展Task模型,如下所示:
root_node = models.ForeignKey('self', null=True,
related_name='descendant_tasks',
verbose_name=_('root task')
)
为了使MP关系明确,以便进行查询。然而,这种方法似乎有点不够DRY,因此我想知道是否有其他建议来解决它。