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

Django Rest Framework中validated_data丢失数据问题排查

问题分析与解决方案

核心原因

你的request.data中,ingredients和directions字段是JSON字符串数组(例如'{"name":"dfgdfg","amount":"gdfgd"}'),但RecipeSerializer中的嵌套序列化器(IngredientSerializer/DirectionSerializer)期望接收的是已经解析完成的Python字典对象,而非字符串。序列化器无法自动将JSON字符串转换为所需的字典结构,导致验证失败——这就是为什么你必须添加required=False才能通过基础验证,但validated_data中仍然没有这两个字段的原因。

另外,name和description字段的值带有额外引号(如'"fdgdfgdf"'),也是前端发送格式的问题,导致你需要在create方法中手动去除引号。


解决方案

方案1:前端调整数据发送格式(推荐)

如果可以修改前端代码,不要将JSON字符串塞入FormData,而是使用DRF支持的嵌套字段表单格式传递数组:

  • 对于ingredients数组,循环每个元素,用ingredients[索引][字段名]作为FormData的键,示例代码:
    const formData = new FormData();
    // 处理ingredients
    ingredients.forEach((ingredient, index) => {
      formData.append(`ingredients[${index}][name]`, ingredient.name);
      formData.append(`ingredients[${index}][amount]`, ingredient.amount);
    });
    // 处理directions
    directions.forEach((direction, index) => {
      formData.append(`directions[${index}][content]`, direction.content);
    });
    // 添加其他字段
    formData.append('name', name);
    formData.append('description', description);
    formData.append('image', imageFile);
    

这种格式下,DRF会自动将参数解析为嵌套的字典数组,序列化器可以直接识别并验证,无需后端额外处理。

方案2:后端手动解析JSON字符串

如果前端无法修改,在视图中先解析request.data中的JSON字符串,再传入序列化器:
修改views.py的POST逻辑:

@api_view(["GET","POST"])
def api_list(request):
    if request.method=="GET":
        data = Recipe.objects.all()
        serializer = RecipeSerializer(data, many=True)
        return Response(serializer.data)

    elif request.method=="POST":
        import json
        # 复制request.data(QueryDict默认不可变)
        data = request.data.copy()
        
        # 解析ingredients字段
        if 'ingredients' in data:
            try:
                # 逐个解析JSON字符串为字典
                data['ingredients'] = [json.loads(item) for item in data.getlist('ingredients')]
            except json.JSONDecodeError:
                return Response({"error": "无效的ingredients JSON格式"}, status=status.HTTP_400_BAD_REQUEST)
        
        # 解析directions字段
        if 'directions' in data:
            try:
                data['directions'] = [json.loads(item) for item in data.getlist('directions')]
            except json.JSONDecodeError:
                return Response({"error": "无效的directions JSON格式"}, status=status.HTTP_400_BAD_REQUEST)
        
        serializer = RecipeSerializer(data=data)
        print("Validating..")
        if serializer.is_valid():
            print("validated!")
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        print (serializer.errors)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

处理完成后,serializer接收的data中ingredients和directions会是字典数组,嵌套序列化器可以正常验证并将其纳入validated_data,此时你可以移除序列化器字段中的required=False。


额外优化

针对name和description字段的引号问题,建议前端直接传递纯字符串值(不要带引号),这样后端无需在create方法中手动执行replace('"','')操作,避免额外的字符串处理逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 20:15:38