Выполнение подзапроса, суммы и соединения в django ORM

У меня есть 2 модели django, которые не связаны ForeignKey из-за унаследованной системы.

class Parent(model):
    name -> CharField()

class Child(model)
    parent_name -> CharField()
    cost        -> IntegerField()

Я хочу добиться левого соединения, которое дает мне все родительские столбцы вместе с суммой стоимости столбцов из дочерних. SQL в postgres переводится как

select parent.name, sum(child.cost) as cost from parent join child on parent.name = child.parent_name group by parent.name;

Есть ли способ достичь этого с помощью django ORM

Я перепробовал много вещей, но https://code.djangoproject.com/ticket/28296 может быть тем, что блокирует.

Пожалуйста, используйте ForeignKey для ссылки на родителя, а не CharField, который присоединяется к имени. Это гарантирует референтную целостность, позволяет избежать дублирования данных и делает более удобными запросы в Django.

Таким образом, вы определяете модели следующим образом:

class Parent(models.Model):
    name = models.CharField(max_length=128)

class Child(models.Model):
    parent = models.ForeignKey(
        Parent,
        on_delete=models.CASCADE
    )
    cost = models.IntegerField()

или если name из Parent уникален, вы можете позволить ему ссылаться на name:

class Parent(models.Model):
    name = models.CharField(max_length=128, unique=True)

class Child(models.Model):
    parent = models.ForeignKey(
        Parent,
        to_field='name',
        db_column='parent_name',
        on_delete=models.CASCADE
    )
    cost = models.IntegerField()

тогда вы можете .annotate(…) [Django-doc] модель Parent с:

from django.db.models import Sum

Parent.objects.annotate(
    cost=Sum('child__cost')
)

объекты Parent, возникающие из этого кверисета, будут иметь дополнительный атрибут .cost, который будет содержать сумму cost из Child, указывающих на этот Parent.

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