3

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ますが、Materialized Path 構造を使用しているdjango-treebeardため、タスク モデル間に Django の関係がないためprefetch_related、すぐに何をすべきかわかりません。カスタム Prefetch オブジェクトを使用しようとしましたが、これにはまだ Django リレーション パスが必要であるため、機能させることができませんでした。

私の現在の考えは、次のようなルート ノードを指す外部キーを使用して Task モデルを拡張することです。

root_node = models.ForeignKey('self', null=True,
                              related_name='descendant_tasks',
                              verbose_name=_('root task')
                              )

MP 関係を明示的にして照会できるようにするため。ただし、これは少し乾燥していない方法のように感じるので、それに取り組む方法について別の提案があるかどうか疑問に思います.

4

2 に答える 2