title: How to prefetch descendants with django-treebeard's MP_Node?
body: <p>I'm developing an application with a hierarchical data structure in <code>django-rest-framework</code> using <code>django-treebeard</code>. My (simplified) main model looks like this </p>
  
  <pre><code>class Task(MP_Node):
      name = models.CharField(_('name'), max_length=64)
      started = models.BooleanField(default=True)
  </code></pre>
  
  <p>What I'm currently trying to achieve is a list view of all root nodes which shows extra fields (such as whether all children have started). To do this I specified a view:</p>
  
  <pre><code>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)
  </code></pre>
  
  <p>and serializer</p>
  
  <pre><code>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))
  </code></pre>
  
  <p>This all works and I get the expected results. However, I run into a N+1 query problem where for each root task I need to fetch all children separately. Normally this would be solvable using <code>prefetch_related</code> but as I use the Materialized Path structure from <code>django-treebeard</code> there are no Django relationships between the task models, so <code>prefetch_related</code> doesn't know what to do out of the box. I've tried to use custom Prefetch objects but as this still requires a Django relation path I could not get it to work. </p>
  
  <p>My current idea is to extend the Task model with a foreign key pointing to its root node like such:</p>
  
  <pre><code>root_node = models.ForeignKey('self', null=True,
                                related_name='descendant_tasks',
                                verbose_name=_('root task')
                                )
  </code></pre>
  
  <p>in order to make the MP relationship explicit so it can be queried. However, this does feel like a bit of a non-dry method of doing it so I wonder whether anyone has another suggestion on how to tackle it.</p>