Django中如何从ForeignKey关联模型取值并求和?
解决Django一对多关系中聚合求和的问题
首先,咱们先理清问题所在:你遇到的报错是因为一个EmpLoan对应多个EmpInstallment,但你在模板里直接用emploan.installment.nominal,相当于尝试从一对多关系中获取单个对象,而实际返回了多个,所以触发了错误。另外,你的关联字段的related_name是empinstallment,不是installment,这也是导致访问失败的原因之一。
下面给你两种解决方案,优先推荐第一种(性能更优):
方法一:在视图中用数据库聚合提前计算总和
这种方法直接在数据库层面完成求和,避免模板中多次查询数据库,性能更好。
修改你的EmpLoanListView,使用Sum聚合函数给每个EmpLoan对象添加一个total_installment字段,存储对应分期的总金额:
from django.db.models import Sum from django.views.generic import ListView import models # 确保导入你的模型 class EmpLoanListView(ListView): context_object_name = 'emploans' model = models.EmpLoan def get_queryset(self): # 给每个贷款对象添加总分期金额的聚合字段 return super().get_queryset().annotate( total_installment=Sum('empinstallment__nominal') ) def get_context_data(self, **kwargs): context = super(EmpLoanListView, self).get_context_data(**kwargs) context['form'] = EmpLoanForm() return context
然后在模板中直接使用这个预计算好的字段:
{% for emploan in emploans %} <tr> <td>{{ emploan.employee.name }}</td> <td>{{ emploan.nominal|intcomma }},-</td> <td>{{ emploan.total_installment|default:"0"|intcomma }},-</td> </tr> {% endfor %}
这里加了|default:"0"是为了处理没有分期的贷款,避免显示空值。
方法二:在模板中遍历求和(不推荐,性能较差)
如果暂时不想修改视图,也可以在模板中遍历所有分期并累加,但这种方法会对每个贷款发起额外的数据库查询,数据量大时性能会受影响:
{% for emploan in emploans %} <tr> <td>{{ emploan.employee.name }}</td> <td>{{ emploan.nominal|intcomma }},-</td> <td> {% with total=0 %} {% for installment in emploan.empinstallment.all %} {% total = total + installment.nominal %} {% endfor %} {{ total|intcomma }},- {% endwith %} </td> </tr> {% endfor %}
额外建议:完善模型的外键设置
你的EmpInstallment模型中的loan外键没有设置on_delete参数,这在Django中是必填项,建议补充上,比如使用CASCADE(删除贷款时自动删除对应的分期):
class EmpInstallment(models.Model): nominal = models.DecimalField(max_digits=10, decimal_places=0) loan = models.ForeignKey(EmpLoan, related_name='empinstallment', on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now=True)
内容的提问来源于stack exchange,提问作者Dicky Raambo
相关产品推荐
相关产品推荐

