django-treebeard
を使用してdjango-rest-framework
の階層データ構造を持つアプリケーションを開発しています。私(簡体字)メインモデルは、私が現在達成しようとしていること(例えば、すべての子どもたちが開始されているかどうかなど)の余分なフィールドを示し、すべてのルート・ノードのリストビューで、このDjango-treebeard MPノードのプリフェッチ子孫
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
は何をするのか分かりません。私はカスタムプリフェッチオブジェクトを使用しようとしましたが、これはまだDjangoリレーションパスが必要なので、動作させることができませんでした。
私の現在の考えは、このようなのようなそのルートノードを指す外部キーでタスクモデルを拡張することです。それが照会できるように、MPの関係を明示的にするために
root_node = models.ForeignKey('self', null=True,
related_name='descendant_tasks',
verbose_name=_('root task')
)
。しかし、これは非乾式の方法のように感じるので、誰かがそれに取り組む方法について別の提案をしているかどうかは疑問です。私は必ず私は常にを指すようにするために私のタスクモデルにメソッドを保存し、更新
root_node = models.ForeignKey('self', null=True,
related_name='descendant_tasks',
verbose_name=_('root task')
)
:私は、このようなのようなそのルートノードを指し示す各タスクへの外部キーを追加することになってしまいました最後に