Django - значение агрегированных полей из объединенной модели - PullRequest
0 голосов
/ 28 февраля 2020

Моя цель здесь проста: отобразить сумму (агрегацию) определенной области сторонней модели. Сложность состоит в текущей настройке, пожалуйста, посмотрите и дайте мне знать, если это нужно изменить, или я могу достичь цели с текущей моделью:

class Route(models.Model):
name = models.CharField(max_length=50)
route_length = models.IntegerField()

class Race(models.Model):
race_cod = models.CharField(max_length=6, unique=True)
route_id = models.ForeignKey(Route, on_delete=models.CASCADE, related_name='b_route')

class Results(models.Model):
race_id = models.ForeignKey(Race, on_delete=models.CASCADE, related_name='r_race')
runner_id = models.ForeignKey(Runner, on_delete=models.CASCADE, related_name='r_runner')

Теперь я пытаюсь получить например, итоги за год:

Бегун X участвовал в 12 гонках с общим расстоянием 134 км.

Хотя мне удалось подсчитать количество таких гонок, как это (views.py)

runner = Runner.objects.get(pk=pk)
number_races = Results.objects.filter(runner_id=runner).count()

Для вычисления расстояния, которое я пробовал:

distance = Results.objects.filter(runner_id=runner).annotate(total_km=Sum(race_id.route_id.route_length))

Этот код содержит ошибку, сообщающую, что на views.py - линия расстояния

Тип исключения: NameError Значение исключения: имя 'race_id' не определено

Я уверен, что не понял, как именно это работает. Кто-нибудь достаточно любезен, чтобы прояснить этот вопрос?

Спасибо

Ответы [ 3 ]

1 голос
/ 01 марта 2020

Мой обходной путь следующий:

    tmp_race_id = Results.objects.filter(runner_id=runner).values('race_id')
    tmp_route_id = Race.objects.filter(pk__in=tmp_race_id).values('route_id')
    distance = Route.objects.filter(pk__in=tmp_route_id).aggregate(Sum("route_length "))['route_length __sum'] or 0.00

Спасибо Хорхе Лопесу за подсказку.

0 голосов
/ 04 марта 2020

делай так

from django.db.models import Sum, Count

u = Runner.objects.annotate(
    tot_result=Count('r_runner'), 
    tot_km=Sum('r_runner__race_id__route_id__route_length')
)

for i in u: 
    print('Total_race {} -- Total_Km {}'.format(i.tot_result, i.tot_km)) 
0 голосов
/ 28 февраля 2020

вам не нужна модель результатов, вы можете рассчитать, используя данные в моделях, можете ли вы поделиться своей моделью бегуна? эта модель должна иметь внешний ключ к гонке. если это так, вы можете go из Route's -> Race -> Runner в своем запросе, и вы можете использовать запрос для подсчета, так что у вас будет переменная, в которой вы сохранили счет, и переменная, в которой вы сохранили расстояние. Чтобы сделать сумму в своем запросе, не используйте аннотирование, используйте агрегат, что-то вроде этого:

.aggregate(total=Coalesce(Sum('route_lenght'), 0))['total']
...