5

django-treebeard 또는 아마도 django-mptt을 사용할 계획 인 데이터베이스에 트리 데이터 구조를 저장해야합니다. 내 혼란의 원인은 각 노드가 세 가지 가능한 유형 중 하나 일 수 있다는 것입니다. 루트 노드는 항상 유형 A 엔티티이고, 리프 노드는 유형 C 엔티티이며, 그 사이의 모든 것은 유형 B 엔티티입니다. 이 상황을 모델링하는 가장 좋은 방법을 알고 싶습니다.Django : 이기종 데이터 유형의 트리를 어떻게 모델링합니까?

업데이트 : 내가 처음 모델 상속을 시도했는데, 이것이 최선의 방법이라고 생각합니다 불행히도 django-treebeard의 공용 API는 실제로이를 처리 할 수있는 API가 아닙니다. 나는 GenericForeignKey를 사용하기 시작했다. 답변 해 주셔서 대단히 감사합니다.

답변

3

표현하는 노드의 콘텐츠 개체에 트리 구조를 보유 할 모델의 generic relation을 사용하는 방법은 어떻습니까?

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') 

이 잠재적으로 전체 트리 콘텐츠 객체를 검색 할 때 쿼리가 많이 발생하지만, 필요한 쿼리 수를 줄이는 ways and means가 있었다. 뿌리, 잎, 이미 다른 사람이 본질적으로 나무 API로 식별되기 때문에

# 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) 
3

세 가지 유형이 기본 트리와 FK 연관으로 가장 쉽게 처리 될 수 있습니다.

트리는 동질성 일 수 있습니다. 클래스 MyNodetreebeard.Node의 직접 하위 클래스입니다. 노드는 플래그 (Root, Middle, Leaf) 및 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 버전으로 바꿔야합니다. 이것은 불가능하지 않지만 고통 스러울 수 있습니다.

1

은 음, 많은 이미, 방법으로, 당신을 위해 수행됩니다. 개별 노드에서 is_root() 및 is_leaf()를 호출하여 구별 할 수 있습니다.

잎과 인맥은 동일한 유형의 엔티티 일 수 있으며 is_leaf() 테스트에 따라 데이터가 응용 프로그램에서 해석되고 사용되는 방식으로 동일한 유형의 데이터를 보유 할 수 있습니다.

루트는 다소 특이합니다. 루트는 전체 트리와 관련된 정보를 보유하고자 할 수 있으며 특정 루트를 찾고 추가 데이터를 보유하는 간단한 방법을 원할 수 있습니다. 루트 노드와 일대일 관계를 가진 모델을 사용하여이를 수행 할 수 있습니다 (아마도 save 메소드가 오버로드되어 있고 저장을 허용하기 전에 노드가 is_root()를 가리키는 지 확인하기 위해 점검해야합니다).

전반적인 요점은 당신이 원하는 것을하기 위해 당신이 매우 공상 할 필요가 없다는 것입니다. 당신이 만들고있는 구별은 이미 트리와 그 API의 개념에 캡슐화되어 있으며 아마도 노드의 컨텍스트를 확인하여 동일한 기본 데이터로 다른 동작을 구현할 수 있습니다.

0

트리 구조가 응용 프로그램의 필수 부분 인 경우 관계형 데이터베이스 이외의 다른 것을 사용하는 것이 좋습니다. 어쩌면 neo4j?

관련 문제