在Django中对关联字段的列进行求和计算
解决Django聚合求和的TypeError问题
这个错误的根源其实很简单——你误用了Python内置的sum()函数,而不是Django ORM专门提供的Sum聚合类!下面帮你一步步修正:
错误原因分析
Python的sum()是用来对**可迭代对象(比如列表、元组)**求和的,它不能直接接收字符串格式的字段名。而你之前的写法把字符串'trip_distance'传给了sum(),导致Python试图把默认的初始值(int类型的0)和字符串相加,自然就抛出了TypeError: unsupported operand type(s) for +: 'int' and 'str'这个错误。
Django ORM的aggregate()方法需要搭配ORM自带的聚合类(比如Sum、Avg等)使用,这些类会帮你生成对应的SQL聚合语句,正确操作数据库字段。
正确实现方式
1. 在Car模型中添加计算属性
首先需要从django.db.models导入Sum,然后修改你的distance_driven属性:
from django.db.models import Sum from django.conf import settings from django.db import models from django.core.validators import MinValueValidator import datetime class Fillup(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE) date = models.DateField(default=datetime.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) @property def distance_driven(self): # 使用Sum聚合函数,指定要求和的字段,并用or 0.0处理无记录的情况 total = self.fillups.aggregate(total_distance=Sum('trip_distance'))['total_distance'] return total or 0.0
2. 在序列化器中实现
同样需要导入Sum,然后修改你的SerializerMethodField方法:
from django.db.models import Sum from rest_framework import serializers from .models import Car class CarSerializer(serializers.ModelSerializer): distance_driven = serializers.SerializerMethodField() def get_distance_driven(self, ob): total = ob.fillups.aggregate(total_distance=Sum('trip_distance'))['total_distance'] # 当车辆没有任何加油记录时,返回0.0而不是None,更符合前端预期 return total or 0.0 class Meta: model = Car fields = ['id', 'user', 'name', 'distance_driven']
额外说明
- 使用
aggregate()会返回一个字典,键是你指定的别名(比如上面的total_distance),值是聚合后的结果。 - 加上
or 0.0是为了处理车辆还没有任何Fillup记录的情况,避免返回None,让返回值类型保持一致(始终是float)。
内容的提问来源于stack exchange,提问作者Chowdahhh
相关产品推荐
相关产品推荐

