Следующая модель содержит две почти идентичные функции 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')
@Sayse: Я не понимаю ваш вопрос. Предки - это обобщение родителей, поэтому 'list_ancestors' использует' list_parents'. Потомки - это обобщение детей, поэтому 'list_descendants' использует' list_children'. – Watchduck
'list_ancestors' сначала получает родителей, а затем рекурсивно получает предков родителей. 'list_descendants' сначала получает детей, а затем рекурсивно получает потомков детей. Поскольку эти две аналогичные функции, которые я пытаюсь унифицировать, являются рекурсивными, мое «решение» 'list_withindirect' также рекурсивно. – Watchduck
О, извините, я пропустил эту часть – Sayse