Работая над одним проектом, я столкнулся с необходимостью хранить подразделения компании в виде древовидной структуры. Реализовал я это так:
упрощенная модель подразделения:
т.е. модель ссылается сама на себя. Ключевое слово здесь path: тут мы будем хранить «путь» к текущей модели через всех предков. Для автоматической его генерации переопределяем save:
таким образом, при сохранении объекта происходит «перегенерация» поля path у всех его потомков.
Теперь выбрать, скажем, всех сотрудников данного и всех вложенных в него подразделений можно простым запросом:
для окончательного наведения красоты определим __str__ для объекта Department:
теперь во всех формах при выборе подразделения будет видна степень его вложенности.
упрощенная модель подразделения:
class Department(models.Model):
name=models.CharField(maxlength=255,null=False,blank=False)
code=models.CharField(maxlength=15,unique=True,null=False,blank=False)
path=models.CharField(maxlength=255,null=False,editable=False)
parent=models.ForeignKey('self',null=True,blank=True)
т.е. модель ссылается сама на себя. Ключевое слово здесь path: тут мы будем хранить «путь» к текущей модели через всех предков. Для автоматической его генерации переопределяем save:
def save(self):
if self.parent:
self.path='%s%s/' % (self.parent.path,self.code)
else:
self.path='/%s/'%self.code
super(type(self),self).save()
for a in Department.objects.filter(parent=self.id):
a.save()
таким образом, при сохранении объекта происходит «перегенерация» поля path у всех его потомков.
Теперь выбрать, скажем, всех сотрудников данного и всех вложенных в него подразделений можно простым запросом:
staff=Staff.objects.filter(department__path__startswith=department.path)
для окончательного наведения красоты определим __str__ для объекта Department:
def __str__(self):
return "%s%s" % ('------'[:self.path.count('/',2)-1],self.name)
теперь во всех формах при выборе подразделения будет видна степень его вложенности.