DRF 序列化器上下文添加delivery_date后嵌套序列化器取值失败
1. 核心致命问题:重写get_serializer_context缺少返回逻辑
DRF的get_serializer_context方法的作用是生成传递给所有关联序列化器的公共上下文,你在完成自定义字段的写入后,没有把修改后的上下文对象返回,导致整个序列化流程拿到的上下文根本不包含你添加的delivery_date字段。
对应修复后的视图代码:
class FoodRetrieveAPIView(RetrieveAPIView): serializer_class = serializers.FoodRetrieveSerializer permission_classes = [IsAuthenticated] queryset = models.Food.objects.all() def get_serializer_context(self): context = super().get_serializer_context() query_params = self.request.query_params delivery_date = query_params.get("delivery_date") context["delivery_date"] = delivery_date # 必须返回修改后的context,否则自定义上下文不会生效 return context
2. 代码语法类问题排查
(1)序列化器父类拼写错误
定义ItemValueRetrieveSerializer时,父类写为serializer.ModelSerializer,缺少复数形式的s,正确写法为serializers.ModelSerializer,否则类定义直接触发报错,序列化流程无法正常执行。
(2)方法缩进不符合Python规范
FoodItemSerializer.get_item方法的方法体没有做标准缩进,会直接触发IndentationError,导致嵌套序列化的逻辑完全无法运行。
3. 嵌套序列化器的上下文透传验证
完成上面两处核心问题修复后,你原有的手动传递context的逻辑是可以正常生效的:外层的FoodItemSerializer拿到包含delivery_date的完整上下文后,在get_item方法里手动实例化ItemValueRetrieveSerializer时传入context=self.context,就能把上下文完整传递到最内层的序列化器中。
如果仍然存在取值异常,可以在get_value方法里加临时打印验证上下文内容:
def get_value(self, obj): # 临时打印验证上下文是否包含目标字段 print("当前序列化器上下文内容:", self.context) delivery_date = self.context.get("delivery_date") food_value = obj.get_food_value(delivery_date=delivery_date)
可选优化方案
如果不想在每个嵌套的SerializerMethodField里重复手动传递context,可以把嵌套的序列化器直接作为字段声明,DRF会自动完成外层上下文的透传,不需要手动写传递逻辑:
class FoodItemSerializer(serializers.ModelSerializer): # 通过source指定关联的模型方法,直接关联子序列化器 item = ItemValueRetrieveSerializer(source="get_item")
这种方式和手动实例化传递context的效果完全一致,还能减少冗余代码。
内容的提问来源于stack exchange,提问作者kaiser

