You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中高效统计模型外键关联的实例总数?

问题原因

你之前的优化方案结果不对,核心原因是Count('house', distinct=True)统计的是单条Fetch记录关联的House对象数量,因为一条Fetch只关联一个House,所以结果永远是1,完全没有统计该House下所有关联Fetch的总数。

解决方案

方案1:直接在Fetch查询层添加关联计数注解(最适合当前场景)

只需要修改你的QuerySet注解逻辑,通过双下划线跨关联关系统计对应House、Person下的所有Fetch总数即可,整个查询只会执行1次SQL,完全解决N+1问题:

from django.db.models import Count

class HomeView(ListView):
    queryset = Fetch.objects.select_related(
        'house', 'person'
    ).annotate(
        # 统计当前Fetch关联的House下所有Fetch总数
        house_fetch_total=Count('house__fetchs', distinct=True),
        # 统计当前Fetch关联的Person下所有Fetch总数
        person_fetch_total=Count('person__person_fetchs', distinct=True)
    )
    template_name = "index.html"
    paginate_by = 100

模板层直接调用注解字段即可,不需要再调用模型的自定义计数方法:

{% for obj in object_list %}
<tr>
    <td>{{ obj.company.name }}</td>
    <td>{{ obj.house_fetch_total }}</td>                   
    <td>{{ obj.person_fetch_total }}</td>
</tr>
{% endfor %}

方案2:全局复用计数逻辑(适合多个视图都需要用到该计数的场景)

如果你的项目中多处需要获取House、Person的关联Fetch总数,可以把计数逻辑封装到模型的查询管理器中,避免重复写注解:

  1. 给House和Person模型添加自定义管理器
from django.db import models
from django.db.models import Count

class HouseManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().annotate(
            fetch_total=Count('fetchs', distinct=True)
        )

class House(models.Model):
    name = models.CharField(max_length=150)
    objects = HouseManager()

class PersonManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().annotate(
            fetch_total=Count('person_fetchs', distinct=True)
        )

class Person(models.Model):
    house = models.ForeignKey(House, related_name="persons", on_delete=models.PROTECT)
    first_name = models.CharField(max_length=150)
    objects = PersonManager()
  1. 之后无论从哪里查询House/Person对象,都可以直接调用fetch_total属性获取计数,Fetch查询只需要保留select_related即可:
queryset = Fetch.objects.select_related('house', 'person')

模板调用:

<td>{{ obj.house.fetch_total }}</td>                   
<td>{{ obj.person.fetch_total }}</td>

注意:你给出的Fetch模型代码里有笔误,house = models.ForeignKey(Hourse, related_name="fetchs")中的Hourse应该是House,请先修正避免运行报错。

内容的提问来源于stack exchange,提问作者PercySherlock

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 11:27:03