2013-07-25 64 views
0

我有以下型號(等等),我嘗試使用封表,inplement樹型結構:如何在Django中使用閉包表查詢祖先列表?

class Part(models.Model): 
    name = models.TextField() 
    quantity = models.IntegerField() 

    manufacturer = models.ForeignKey(Manufacturer) 

    def __str__(self): 
     return "Part {}: {}, {}".format(self.id, self.name, self.quantity) 

    def path(self): 
     ancestors = Part.objects.filter(closures_d__descendant__id__exact=self.id) 
     print(len(ancestors)) 
     return "{}".format(reduce(lambda a, b: a+" > "+b, map(lambda x: x.name, ancestors), "")) 

    class Meta: 
     db_table = 'parts' 

class Closure(models.Model): 

    ancestor = models.ForeignKey(Part, related_name='closures_a') 
    descendant = models.ForeignKey(Part, related_name='closures_d') 

    class Meta: 
     db_table = 'closures' 

問題是path功能不起作用如預期的那樣,取 祖先查詢從數據庫只返回一個對象(調用它的部分)。 我檢查生成的SQL查詢,並且看起來瓶蓋被忽略(從connection.queries輸出):

[{'time': '0.001', 'sql': 'SELECT "parts"."id", "parts"."name", "parts"."quantity", "parts"."manufacturer_id" FROM "parts" WHERE "parts"."id" = 101 '}] 

如何做正確的連接? (我指的Python/Django的方式,我可以用原始SQL做到這一點)

查詢應該是這樣的(101例如ID,部分在DB存在,並且有幾個祖先,下面返回查詢正確的結果):

SELECT * from parts p JOIN closures c ON p.id=c.ancestor_id WHERE c.descendant_id=101 

回答

1

OK,我得到了它的權利,查詢的祖先應該說:

ancestors = Part.objects.filter(closures_a__descendant_id__exact=self.id) 

代替:

ancestors = Part.objects.filter(closures_d__descendant__id__exact=self.id) 

查詢返回正確的結果,但顯示的SQL看起來還是錯誤的(沒有JOIN), 我不知道爲什麼,我得到了使用此代碼(路徑功能從問題類部分)生成的查詢:

def path(self): 
    ancestors = Part.objects.filter(closures_a__descendant_id__exact=self.id) 
    from django.db import connection 
    print(connection.queries) 
    return "{}".format(reduce(lambda a, b: a+" > "+b, map(lambda x: x.name, ancestors), ""))