【问题标题】:Django - aggregate fields value from joined modelDjango - 来自连接模型的聚合字段值
【发布时间】:2020-02-28 19:45:32
【问题描述】:

我的目标似乎很简单:显示外部模型特定字段的总和(聚合)。 困难在于当前的设置,请看一下并告诉我是否需要更改或我可以使用当前模型实现目标:

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')

现在,我正在尝试做一个年度总结:

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”

我确定我并没有完全理解它是如何工作的。有没有好心人澄清一下这个问题?

谢谢

【问题讨论】:

    标签: django aggregate field annotate foreign-collection


    【解决方案1】:

    我的解决方法如下:

        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
    

    感谢 Jorge Lopez 的提示。

    【讨论】:

      【解决方案2】:

      您不需要结果模型,您可以使用模型中的数据进行计算,您可以分享您的跑步者模型吗?该模型需要有一个 Race 的外键。如果是这样,您可以在查询中从 Route's -> Race -> Runner 开始,您可以使用查询来获取计数,因此您将拥有一个存储计数的变量和一个存储距离的变量。要在查询中进行求和,请不要使用注释,使用聚合,如下所示:

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

      【讨论】:

      • 嘿,Runner 类只有 id、跑步者的姓名和一些个人数据。我不能把 FK 放到 Race 那里,因为逻辑是这样的:添加跑步者 -> 添加路线 -> 添加 Race -> 将结果放入 Race。
      • 抱歉,我没能早点回复,我周末没电脑,很高兴你找到了解决方法。
      【解决方案3】:

      这样做

      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)) 
      

      【讨论】:

      • 感谢您在这里的第一个回答。也许你应该考虑用一些有用的代码解释来更新你的答案。
      猜你喜欢
      • 1970-01-01
      • 2016-07-23
      • 2011-11-08
      • 2021-08-24
      • 2023-01-04
      • 2010-12-20
      • 2011-04-04
      • 2018-02-13
      • 1970-01-01
      相关资源
      最近更新 更多