Упрощенный пример структуры моей модели:
class Corporation(models.Model):
...
class Division(models.Model):
corporation = models.ForeignKey(Corporation)
class Department(models.Model):
division = models.ForeignKey(Division)
type = models.IntegerField()
Теперь я хочу отобразить таблицу, в которой отображаются корпорации, в столбце которых будет указано количество отделов определенного типа, например, type=10
.В настоящее время это реализовано с помощью помощника в модели Corporation
, который извлекает их, например,
class Corporation(models.Model):
...
def get_departments_type_10(self):
return (
Department.objects
.filter(division__corporation=self, type=10)
.count()
)
. Проблема в том, что это абсолютно снижает производительность из-за проблемы N + 1.
Я пытался решить эту проблему с помощью select_related
, prefetch_related
, annotate
и subquery
, но я не смог получить нужные мне результаты.
В идеале каждый Corporation
в наборе запросов должен быть аннотирован целым числом type_10_count
, которое отражает количество отделов этого типа.
Я уверен, что мог бы что-то сделать с raw sql в .extra()
, но документы объявляютчто это будет устаревшим (я на Django 1.11)
РЕДАКТИРОВАТЬ: Пример необработанного решения SQL
corps = Corporation.objects.raw("""
SELECT
*,
(
SELECT COUNT(*)
FROM foo_division div ON div.corporation_id = c.id
JOIN foo_department dept ON dept.division_id = div.id
WHERE dept.type = 10
) as type_10_count
FROM foo_corporation c
""")