Агрегация в Джанго - PullRequest
       3

Агрегация в Джанго

1 голос
/ 05 июля 2019

У меня есть следующая модель в Джанго:

class A(models.Model):
    nr = models.IntegerField()

class B(models.Model):
    points = models.IntegerField()

class C(models.Model):
    a = models.ForeignKey(A, on_delete=models.CASCADE)
    b = models.ForeignKey(B, on_delete=models.CASCADE)

Таким образом, для каждого A есть много записей в C, и для каждого B есть также много записей в C. Но для каждой записи в C есть ровно одна запись в A и одна в B.

Я бы хотел суммировать баллы B. для данного A, но мне нужно перейти к C.

Как я могу сделать это в Django? Я бы знал, как это сделать в SQL, если это поможет?

1 Ответ

4 голосов
/ 05 июля 2019

Вы можете .annotate(..) [Django-doc] A s, например:

from django.db.models import Sum

A.objects.annotate(
    <b>total_points=Sum('c__b__points')</b>
)

Если вы, например, всегда хотите аннотироватьваши A объекты, вы можете определить менеджера для этого:

class <b>WithPointsManager</b>(models.Manager):

    def <b>get_queryset</b>(self):
        return super().get_queryset().annotate(
            total_points=Sum('c__b__points')
        )

и затем определить этого менеджера для класса A, например:

class A(models.Model):
    nr = models.IntegerField()

    <b>objects = WithPointsManager()</b>

Так что теперь, если вывыполнить A.objects.all(), A s будет иметь атрибут total_points.Обратите внимание, что, конечно, это будет иметь определенную стоимость на стороне базы данных.

Тогда все A объекты, которые возникают из этого QuerySet, будут содержать дополнительный атрибут .total_points, который содержит сумму всех B s, которые связаны с C, который связан с этим A.

Или для данного A объекта вы можете .aggregate(..) [Django-doc] , например:

from django.db.models import Sum

some_a.c_set.aggregate(
    <b>total_points=Sum('b__points')</b>
)<b>['total_points']</b>

Возвращает сумму points связанных B объектов из набора C s, связанных с some_a.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...