我有以下模型(除其他外),我试图使用闭包表来实现树结构:
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