次のモデルには、2つのほぼ同じ機能list_ancestors
とlist_descendants
が含まれています。このコードを一度書くだけの良い方法は何でしょうか?同様のDjangoモデルメソッドでコードの重複を避けるには?
class Node(models.Model):
name = models.CharField(max_length=120, blank=True, null=True)
parents = models.ManyToManyField('self', blank=True, symmetrical=False)
def list_parents(self):
return self.parents.all()
def list_children(self):
return Node.objects.filter(parents=self.id)
def list_ancestors(self):
parents = self.list_parents()
ancestors = set(parents)
for p in parents:
ancestors |= set(p.list_ancestors()) # set union
return list(ancestors)
def list_descendants(self):
children = self.list_children()
descendants = set(children)
for c in children:
descendants |= set(c.list_descendants()) # set union
return list(descendants)
def __str__(self):
return self.name
EDIT:以下の回答から得られる解決策:
def list_withindirect(self, arg):
direct = getattr(self, arg)()
withindirect = set(direct)
for d in direct:
withindirect |= set(d.list_withindirect(arg))
return list(withindirect)
def list_ancestors(self):
return self.list_withindirect('list_parents')
def list_descendants(self):
return self.list_withindirect('list_children')
@質問:私はあなたの質問を理解していません。祖先は親の一般化されたものなので、 'list_ancestors'は' list_parents'を使います。子孫は子どもの一般化されたものなので、 'list_descendants'は' list_children'を使います。 – Watchduck
'list_ancestors'はまず親を取得し、次に親の祖先を再帰的に取得します。 'list_descendants'はまず子を取得し、子の子孫を再帰的に取得します。私が統合しようとするこれら2つの同様の関数が再帰的であるため、私の "解" list_withindirectも再帰的です。 – Watchduck
ああ申し訳ありませんが、私はその部分を逃しました – Sayse