【问题标题】:Summing columns in Django with related fields将 Django 中的列与相关字段相加
【发布时间】:2022-01-21 05:58:18
【问题描述】:

我正在尝试对我的一些 Django 列进行一些聚合,但我遇到了一个我无法弄清楚的错误。这是我的模型(反正相关的东西):

class Fillup(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
    date = models.DateField(default=date.today)
    trip_distance = models.FloatField(validators=[MinValueValidator(0.0)])
    car = models.ForeignKey('Car',on_delete=models.CASCADE, related_name='fillups')


class Car(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
    name = models.CharField(max_length=25)

因此,每个 Fillup 对象本质上都是汽车中的一罐油,而我想要做的是获取每辆汽车的 trip_distance 列的总数。我从其他各种 StackOverFlow 页面尝试了几件事,但似乎没有任何效果。

我的第一次尝试是将此字段添加到汽车模型:

@property
def distance_driven(self):
    return self.fillups.aggregate(sum('trip__distance'))

但我只是收到以下错误:

TypeError: unsupported operand type(s) for +: 'int' and 'str'

我也尝试将它添加到我的序列化程序中,但得到了同样的错误:

distance_driven = serializers.SerializerMethodField()

def get_distance_driven(self, ob):
    return ob.fillups.all().aggregate(sum('trip_distance'))['trip__distance']

这里有什么我遗漏的吗?我不明白为什么在尝试对 FloatField 列求和时出现该错误。

任何帮助将不胜感激!

【问题讨论】:

    标签: django django-models django-rest-framework


    【解决方案1】:

    为了聚合,您使用Sum object [Django-doc],而不是Python builtin sum

    您可以通过以下方式获得单个对象的总和:

    from django.db.models import Sum
    
    return self.fillups.aggregate(total=Sum('trip_distance'))['total']

    如果必须对多条记录执行此操作,最好.annotate(…) [Django-doc]

    from django.db.models import Sum
    
    Car.objects.annotate(
        total_distance=Sum('fillups__trip_distance')
    )

    由此查询集产生的Car 对象将有一个额外的属性.total_distance 以及相关Fillup trip_distances 的总和。

    【讨论】:

    • 我刚刚在视图中将注释添加到我的get_queryset,但现在我收到以下错误:django.core.exceptions.ImproperlyConfigured: Field name total_distance is not valid for model Car Do除了将“total_distance”添加到字段列表之外,我还需要更新序列化程序吗?
    • @Chowdahhh:您是否将序列化程序中的total_distance 字段更改为sreializers.FloatField()
    • 我没有!一旦我将该字段添加到我的序列化程序(total_distance=serializers.FloatField()),它就起作用了。感谢您的帮助!
    猜你喜欢
    • 2011-08-06
    • 2021-08-15
    • 2020-09-03
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 2015-08-01
    • 2013-05-11
    • 1970-01-01
    相关资源
    最近更新 更多