0

我有以下模型(除其他外),我试图使用闭包表来实现树结构:

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
4

1 回答 1

1

好的,我猜对了,查询祖先应该说:

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), ""))
于 2013-07-25T20:04:18.927 回答