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

DRF访问WorkoutExercise详情接口报RelatedManager无description错误

接口请求异常问题记录

发起对地址为 http://167.71.57.114/api2/workout-exercises/3 的请求,目标是获取编号为3的 WorkoutExercise 对象详情视图数据。

请求执行时抛出 AttributeError 异常:序列化器在为 ExerciseSerializer 的 description 字段取值时失败,该序列化字段命名存在偏差,无法匹配 RelatedManager 实例上的任何属性或键,原始异常信息为:'RelatedManager' object has no attribute 'description'。


相关代码实现

serializers.py

class WorkoutExerciseSerializer(serializers.ModelSerializer):
    exercises = ExerciseSerializer()

    class Meta:
        model = WorkoutExercise
        fields = ('week', 'exercises')

views.py

class WorkoutExerciseViewSet(viewsets.ModelViewSet):
    queryset = WorkoutExercise.objects.all()
    serializer_class = WorkoutExerciseSerializer
    http_method_names = ['get', 'post']

models.py

class WorkoutExercise(models.Model):
    workout_program = models.ForeignKey(WorkoutProgram, on_delete=models.CASCADE, related_name='workout_exercises')
    week = models.PositiveIntegerField(default=1)
    day = models.PositiveIntegerField(default=1)
    order = models.PositiveIntegerField(default=1)

    def save(self, *args, **kwargs):
        if not self.pk:
            last_order = WorkoutExercise.objects.all().aggregate(largest=models.Max('order'))['largest']
            if last_order is not None:
                self.order = last_order + 1
        return super(WorkoutExercise, self).save(*args, **kwargs)

    def get_workout_programs(self):
        return self.workout_program.name

    def get_exercises(self):
        pass

    def __str__(self):
        return self.workout_program.name

    class Meta:
        ordering = ('week', 'day')

问题根因与修复方案

  • 根因
    • 序列化器中配置的 exercises = ExerciseSerializer() 是单对象序列化写法,仅适配单外键、一对一这类单个关联对象的场景。当前 WorkoutExercise 模型并未定义指向 Exercise 的正向关联字段,序列化器读取 exercises 属性时,实际命中了ORM自动生成的反向关联 RelatedManager 管理器(该对象是用来操作多个关联集合的实例,不是单个 Exercise 模型对象),因此无法读取到 description 这类属于单个模型实例的字段。
    • 序列化器配置的字段名和模型实际的关联字段名不匹配,错误触发ORM反向关联解析逻辑,拿到了类型不符合预期的管理器对象。
  • 修复步骤
    1. 梳理模型关联关系:如果单条 WorkoutExercise 记录对应多个训练动作(一对多/多对多关联),需要在序列化器的嵌套字段上开启多对象序列化支持,修改为:
      exercises = ExerciseSerializer(many=True)
      
    2. 如果单条 WorkoutExercise 记录对应单个训练动作(单外键关联),需要先在模型中补充正向关联字段,例如:
      exercise = models.ForeignKey(Exercise, on_delete=models.CASCADE, related_name='workout_entries')
      
      同时将序列化器中的字段名调整为和模型字段完全一致,避免触发反向关联解析。
    3. 逐一对齐序列化字段与模型属性的命名,确保嵌套序列化字段的取值类型和序列化器的适配逻辑匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.28 03:36:05