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

Django自定义序列化器:如何从关联模型添加字段?

问题:Django REST Framework序列化器如何添加关联模型的字段?

我现在有这样的Django模型定义:

class Subject(models.Model):
    db = 'default'
    subjectName = models.CharField(max_length = 100)
    cohortID = models.ForeignKey(Cohort, on_delete=models.CASCADE, related_name='subjects')
    teacherID = models.ForeignKey(Teacher, on_delete=models.CASCADE, related_name='subjects', null=True)

class Cohort(models.Model):
    db = 'default'
    school_creator = models.ForeignKey(CustomUser, on_delete = models.CASCADE, related_name='cohorts')
    mainTeacherID = models.ForeignKey(CustomUser, on_delete=models.CASCADE, null=True, related_name='mainCohorts')
    class_name = models.CharField(max_length = 100)

当前使用的Subject序列化器是:

class SubjectSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Subject
        fields = ('subjectName', 'teacherID', 'pk',)

它返回的结果是:

{"subjectName":"Maths","teacherID":2,"pk":4}

我希望返回结果里能包含关联的Cohort模型的class_name字段,命名为cohortName,也就是要得到这样的结构:

{"subjectName":"Maths","teacherID":2,"pk":4, "cohortName" : "4 B"}

我尝试自定义了下面的序列化器,但运行出错,没法实现需求,求指点:

class SubjectCohortSerializer(serializers.ModelSerializer):
    cohortName = serializers.SerializerMethodField(read_only=True)
    class Meta:
        model = models.Subject
        fields = ('subjectName', 'teacherID', 'pk','cohortName')
    def get_cohortName(self, subject):
        return models.Cohort.objects.get(pk=self.context['request'].cohortID.className)

错误分析

你写的get_cohortName方法有两个明显问题:

  1. 完全没必要额外查询数据库——Subject模型已经通过cohortID外键关联到Cohort,直接通过当前的subject对象就能访问关联的Cohort实例,不用重新查库;
  2. self.context['request'].cohortID.className写法完全错误:请求对象里没有cohortID这个属性,而且模型里的字段名是class_name,不是className。

正确解法

这里有两种简单的实现方式,选哪种都可以:

方法1:使用SerializerMethodField(最灵活)

修改你的自定义序列化器,直接从当前subject对象获取关联Cohort的class_name:

class SubjectCohortSerializer(serializers.ModelSerializer):
    cohortName = serializers.SerializerMethodField(read_only=True)
    
    class Meta:
        model = models.Subject
        fields = ('subjectName', 'teacherID', 'pk','cohortName')
    
    def get_cohortName(self, subject):
        # 直接通过外键关联访问Cohort实例的class_name字段
        return subject.cohortID.class_name

方法2:使用SlugRelatedField(更简洁)

如果只是想获取关联模型的某个字段值,用SlugRelatedField更直接,不需要写额外的方法:

class SubjectCohortSerializer(serializers.ModelSerializer):
    cohortName = serializers.SlugRelatedField(
        source='cohortID',
        read_only=True,
        slug_field='class_name'
    )
    
    class Meta:
        model = models.Subject
        fields = ('subjectName', 'teacherID', 'pk','cohortName')

这两种方法都能得到你想要的返回结构,要是担心性能,可以在查询Subject时加上select_related('cohortID')做预查询,减少数据库请求次数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:03:02