Выполнение подзапроса, суммы и соединения в 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.