5

データベースにツリーデータ構造を保存する必要があります。そのために、django-treebeardまたは場合によってはdjango- mpttを使用する予定です。私の混乱の原因は、各ノードが3つの異なるタイプのいずれかである可能性があることです。ルートノードは常にタイプAエンティティ、リーフノードはタイプCエンティティ、その間のものはすべてタイプBエンティティになります。この状況をモデル化するための最良の方法を知りたいです。

更新: 私は最初にモデルの継承を試しましたが、これが最善の方法だと思います。残念ながら、django-treebeardのパブリックAPIは、これを処理するようには実際には設計されていません。GenericForeignKeyで動作するようになりました。回答ありがとうございます。

4

4 に答える 4

3

ツリー構造を保持するモデルから、それが表すノードのコンテンツ オブジェクトへの一般的な関係を使用するのはどうですか?

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class Node(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    object = generic.GenericForeignKey('content_type', 'object_id')

これにより、ツリー全体のコンテンツ オブジェクトを取得するときに多くのクエリが発生する可能性がありますが、必要なクエリの数を減らす方法と手段があります。

# Assuming mptt, as I'm not familiar with treebeard's API

# 1 query to retrieve the tree
tree = list(Node.tree.all())

# 4 queries to retrieve and cache all ContentType, A, B and C instances, respectively
populate_content_object_caches(tree)
于 2008-11-15T12:30:54.817 に答える
3

あなたの 3 つのタイプは、おそらく基本ツリーとの FK 関連付けとして最も簡単に処理できます。

ツリーは同種である可能性があります。クラスMyNodeは の直接のサブクラスですtreebeard.Node。ノードには、フラグ (ルート、ミドル、リーフ) と、A、B、または C の FK を設定できます。これにより、MyNode インスタンスのクエリで SQL のような柔軟性が得られます。

これにより、ツリーを成長させることができます。ノードは、タイプ C (リーフ) として開始し、タイプ B (中間) にモーフィングできます。ステータスを変更し、FK を変更します。

別の方法はもう少し複雑です。

class MyA( treebeard.Node ):
    pass

class MyB( treebeard.Node ):
    pass

class MyC( treebeard.Node ):
    pass

この場合、ノードを「モーフィング」することはできません。ノードが として開始され、MyC子を取得する場合、元のインスタンスを削除し、新しいノードを子として持つバージョンにMyC置き換える必要があります。MyBこれは不可能ではありませんが、痛みを伴う場合があります。

于 2008-11-15T01:51:41.033 に答える
1

根、葉、およびその他は、ツリー API によってすでに本質的に識別されているため、ある意味では、多くのことが既に行われています。個々のノードで is_root() および is_leaf() を呼び出して、それらを区別できます。

リーフとインビトウィーンは同じタイプのエンティティであり、同じタイプのデータを保持できます。アプリケーションがデータを解釈して使用する方法は、is_leaf() のテストに依存します。

ルートはやや特殊です... ツリー全体に関連する情報を保持したい場合があり、特定のルートを検索して追加のデータを保持する簡単な方法が必要な場合があります。これは、ルート ノードと 1 対 1 の関係を持つモデルで行うことができます (おそらく、save メソッドがオーバーロードされ、保存を許可する前にノードが is_root() を指していることを確認するためのチェックを使用して)。

全体として私が言いたいのは、あなたがやりたいことをするのに、それほど派手になる必要はないということです。作成している区別は、ツリーとその API の概念にすでにカプセル化されており、ノードのコンテキストを確認することで、同じ基本データで異なる動作を実装できる可能性があります。

于 2009-12-03T01:13:52.783 に答える
0

ツリー構造がアプリケーションの不可欠な部分である場合は、リレーショナル データベース以外のものを使用することを検討してください。もしかしてneo4j?

于 2010-12-18T18:53:46.490 に答える