私は次のモデルを持っています (とりわけ)、クロージャーテーブルを使用してツリー構造を補完しようとしています:
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
関数が期待どおりに機能しないことです。データベースから先祖をフェッチするクエリは、1 つのオブジェクト (それを呼び出した部分) のみを返します。生成された 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 の例、一部はデータベースに存在し、先祖はほとんどありません。以下のクエリは正しい結果を返します)。
SELECT * from parts p JOIN closures c ON p.id=c.ancestor_id WHERE c.descendant_id=101