Django: Запрос к иерархической модели

Представьте, что есть модель:

class OrgUnit(models.Model):
    parent = models.ForeignKey(
        'self',
        on_delete=models.CASCADE,
        verbose_name=_('parent'),
        related_name='children',
        blank=True,
        null=True,
    )
    name = models.CharField(_('name'), max_length=255)
    type = models.CharField(_('type'), max_length=55, null=True, blank=True, db_index=True)
   

И образец иерархии:

enter image description here

Легко найти все магазины, если знать идентификатор кластера (cluster_id=1):

stores = OrgUnit.objects.filter(
    type='store',
    parent__parent_id=cluster_id
)

Также легко найти кластер по идентификатору отдела продаж (sales_department_id=5):

cluster = OrgUnit.objects.select_related('parent__parent').get(pk=sales_department_id).parent.parent

И наконец-то нашли магазины для отдела продаж:

cluster_id = OrgUnit.objects.select_related('parent').get(pk=sales_department_id).parent.parent_id
stores = OrgUnit.objects.filter(type='store', parent__parent_id=cluster_id)

Получение магазинов по id отдела продаж приведет к 2 запросам к базе данных. Я хотел бы знать, возможно ли получить магазины по id отдела продаж в одном запросе? Если да, то как?

Вы можете снова переместить иерархию вниз с помощью children, таким образом запрашивая отношение ForeignKey в обратном порядке:

stores = OrgUnit.objects.filter(
    type='store',
    parent__parent__children__children__pk=sales_department_id
)

Здесь мы запрашиваем OrgItem, у которых есть родитель, у которого есть родитель, для которого есть ребенок, для которого есть ребенок с первичным ключом sales_department_id.

Вернуться на верх