Pull to refresh

Древовидные объекты в джанге

Reading time1 min
Views2.3K
Работая над одним проектом, я столкнулся с необходимостью хранить подразделения компании в виде древовидной структуры. Реализовал я это так:


упрощенная модель подразделения:
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)


теперь во всех формах при выборе подразделения будет видна степень его вложенности.
Tags:
Hubs:
+3
Comments6

Articles

Change theme settings