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

Django ListView如何为每个培训项查询对应学员人数并添加到上下文

实现方案

最优方案:使用ORM注解聚合查询(仅1次数据库查询,无N+1性能问题)

这是效率最高的实现方式,直接在查询培训列表的同时,给每个培训对象新增学员人数属性,不需要额外循环查询:
首先修改你的视图代码,引入Count聚合函数,重写get_queryset方法:

from django.db.models import Count

class TrainingsView(ListView):
    model = NewHireTraining
    template_name = 'nht/trainings.html'
    context_object_name = 'trainings'

    def get_queryset(self):
        # 给每个培训项注解关联的学员人数,注解后每个培训对象会新增trainee_count属性
        return super().get_queryset().annotate(
            trainee_count=Count('trainee')
        )

注:如果你的Trainee模型中new_hire_training外键没有自定义related_name,默认反向关联名是trainee_set,把上面Count的参数改成'trainee_set'即可。如果要让代码更易读,建议给外键加上related_name配置:

# 修改Trainee模型的外键定义
new_hire_training = models.ForeignKey(NewHireTraining, on_delete=models.CASCADE, related_name='trainees')

改完后Count参数就可以写成'trainees',语义更清晰。

模板中使用方法

直接遍历培训列表即可调用注解生成的人数属性:

{% for training in trainings %}
<div>
    <h3>培训项目:{{ training.program }}-{{ training.project }}</h3>
    <p>开班时间:{{ training.start_date }}</p>
    <p>当前学员人数:{{ training.trainee_count }}</p>
</div>
{% endfor %}

可选进阶:过滤统计规则

如果需要只统计在职(未离职is_term=False)的学员,可以给Count加上过滤条件:

from django.db.models import Count, Q

def get_queryset(self):
    return super().get_queryset().annotate(
        # 仅统计未离职的学员人数
        trainee_count=Count('trainees', filter=Q(trainees__is_term=False))
    )

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 08:45:02