5

클로저 테이블을 사용하여 계층 적 트리로 구성된 데이터를 모델링하려고합니다. 트리의 노드를 나타내는 항목은 공상적인 것이 아니며 다음과 같이 정의됩니다.장고 ORM 및 클로저 테이블

class Region(models.Model): 
    RegionGuid = models.CharField(max_length=40, unique=True, db_column='RegionGUID', blank=True) 
    CustomerId = models.IntegerField(null=True, db_column='CustomerID', blank=True) 
    RegionName = models.CharField(max_length=256, db_column='RegionName', blank=True) 
    Description = models.TextField(db_column="Description", blank=True) 
    class Meta: 
     db_table = u'Region' 

노드 사이의 경로는 다음 클로저 테이블을 사용하여 정의됩니다. 그것은 조상 노드에 FK 구성, FK 조상과 후손의 후손 노드와 경로 길이 (노드 즉, 번호)로 :

나는 모든 Region 행과 각각의 부모 노드를 검색 얼마나 지금
class RegionPath(models.Model): 
    Ancestor = models.ForeignKey(Region, null=True, db_column='Ancestor', blank=True) 
    Descendant = models.ForeignKey(Region, null=True, db_column='Descendant', blank=True) 
    PathLength = models.IntegerField(null=True, db_column='PathLength', blank=True) 
    class Meta: 
     db_table = u'RegionPath' 

(즉, RegionPath.PathLength = 1)? 내 SQL은 약간 녹슬었지만 나는 SQL 쿼리가 이와 같이 보일 것이라고 생각한다.

SELECT r.* from Region as r 
LEFT JOIN 
(SELECT r2.RegionName, p.Ancestor, p.Descendant from Region as r2 INNER JOIN RegionPath as p on r2.id = p.Ancestor WHERE p.PathLength = 1) AS Parent 
on r.id = Parent.Descendant 

Django의 QuerySet API를 사용하여 표현할 때 도움이 될만한 정보가 있으면 알려 주시기 바랍니다. 그래서 같은 외부 키에 related_name을 추가함으로써

+0

다른 언어 (php/codeigniter)로 도움이 될지 모르겠지만 클로저 테이블을 구현하는 데 익숙해졌고 어쩌면 아이디어를 얻을 수있을 것입니다. https://gist.github.com/dazld/2174233 – dmp

+0

링크를 제공해 주셔서 감사합니다.하지만 저에게 도움이되지는 않습니다. 쿼리의 논리를 처리 할 수 ​​있으며 필요한 경우 원시 SQL에 쿼리를 작성할 수 있습니다. 난 그냥 장고 QuerySet API에 의해 난처한 해요. – CadentOrange

+0

클로저 테이블을 사용해야하는 특별한 이유가 있습니까? 예를 들어, 같은 문제를 해결하는 [MPTT] (https://github.com/django-mptt/django-mptt)의 Django 구현이 매우 훌륭합니다. –

답변

1

:

class RegionPath(models.Model): 
    Ancestor = models.ForeignKey(Region, null=True, db_column='Ancestor', blank=True, related_name="ancestor") 
    Descendant = models.ForeignKey(Region, null=True, db_column='Descendant', blank=True, related_name="descendants") 
    PathLength = models.IntegerField(null=True, db_column='PathLength', blank=True) 
    class Meta: 
     db_table = u'RegionPath' 

당신은 관계 중 하나에 대한 쿼리를 만들 수 있습니다

children = Region.objects.filter(ancestors__PathLength=1) 
parents = Region.objects.filter(descendants__PathLength=1) 

나는 매우 비슷한 모델을 내 테스트를했다. .distinct()를 추가해야 할 수도 있습니다. select_related()를 사용하면 쿼리를 줄일 수 있습니다.