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

Django关联School与Student模型统计学校学生数无结果如何解决

Django关联模型统计学生人数修复方案

核心问题原因

  • 统计语句school.objects.annotate(num_of_students=Count('student'))位置错误:写在序列化器类定义体中只会在模块加载时执行一次,不会作用到每次查询的实例上
  • 统计结果字段num_of_students没有加入序列化器的返回字段列表,序列化时自动忽略
  • 外键命名不规范,默认反向关联名不匹配会导致Count统计失效:Student模型中对外键命名为school_id,Django默认生成的反向关联名为student_set,直接写Count('student')找不到关联数据
  • 查询集没有做关联预加载和统计注解,即使序列化器加了字段也拿不到统计值

修复步骤

1. 调整模型(可选但推荐)

规范外键命名,添加反向关联名,同时补全CharField必填的max_length参数:

class School(models.Model):
    name = models.CharField(max_length=100)
    city = models.CharField(max_length=50)
    street = models.CharField(max_length=100)

class Student(models.Model):
    # 外键命名为school,添加related_name方便反向查询
    school = models.ForeignKey(School, on_delete=models.CASCADE, related_name='students')
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)

如果不想修改原有外键名school_id,仅需给外键加related_name即可:

school_id = models.ForeignKey(School, on_delete=models.CASCADE, related_name='students')

2. 调整序列化器

在SchoolSerializer中添加统计字段,加入返回字段列表:

from rest_framework import serializers
from django.db.models import Count
from .models import School, Student

class SchoolSerializer(serializers.HyperlinkedModelSerializer):
    # 新增只读的学生统计字段
    num_of_students = serializers.IntegerField(read_only=True)
    class Meta:
        model = School
        fields = ['name', 'num_of_students']

class StudentSerializer(serializers.HyperlinkedModelSerializer):
    # 如果外键名是school_id,此处需要加source参数:source='school_id'
    school = SchoolSerializer(read_only=True)
    class Meta:
        model = Student
        fields = ['first_name', 'last_name', 'school']

3. 调整视图查询集

在查询时提前做关联加载和统计注解,避免N+1查询问题:

from rest_framework import viewsets
from .models import Student
from .serializers import StudentSerializer

class StudentViewSet(viewsets.ModelViewSet):
    serializer_class = StudentSerializer
    # 预加载关联学校数据,同时注解统计每个学校的学生数
    queryset = Student.objects.select_related('school').annotate(
        num_of_students=Count('school__students')
    )

扩展:直接返回学校维度的统计数据

如果需要直接获取所有学校的学生统计列表,新增School的视图即可:

class SchoolViewSet(viewsets.ModelViewSet):
    serializer_class = SchoolSerializer
    # 直接注解统计每个学校的学生数
    queryset = School.objects.annotate(num_of_students=Count('students'))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 16:15:02