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反向关联解析逻辑,拿到了类型不符合预期的管理器对象。
- 序列化器中配置的
- 修复步骤
- 梳理模型关联关系:如果单条
WorkoutExercise记录对应多个训练动作(一对多/多对多关联),需要在序列化器的嵌套字段上开启多对象序列化支持,修改为:exercises = ExerciseSerializer(many=True) - 如果单条
WorkoutExercise记录对应单个训练动作(单外键关联),需要先在模型中补充正向关联字段,例如:
同时将序列化器中的字段名调整为和模型字段完全一致,避免触发反向关联解析。exercise = models.ForeignKey(Exercise, on_delete=models.CASCADE, related_name='workout_entries') - 逐一对齐序列化字段与模型属性的命名,确保嵌套序列化字段的取值类型和序列化器的适配逻辑匹配。
- 梳理模型关联关系:如果单条
内容的提问来源于stack exchange,提问作者swor
相关产品推荐
相关产品推荐

