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

React中如何在FormData追加列表与文本?Django校验报错求助

问题:React FormData传递列表+文本数据时Django提示product_image必填错误

问题现象

提交请求后收到错误:product_image["This field is required."],明明已在FormData中添加product_image列表,但后端接收到的是JSON字符串,无法被Django序列化器识别。

后端Django要求的数据格式(仅接受此结构)

{
    "Name": "1",
    "category": "1",
    "Description": "1",
    "archive": "true",
    "Banner": {},
    "product_image": [
        {
            "Name": "img[0]",
            "image": {},
            "secret_key": "Keys"
        },
        {
            "Name": "img[1]",
            "image": {},
            "secret_key": "Keys"
        }
    ]
}

注:{}代表文件对象

前端定义的数据

const p_details = { 
    "Name": "1", 
    "category": 1, 
    "Description": "1", 
    "archive": true, 
    "Banner": {} 
}

const p_img = { 
    "Name": "img", 
    "Image": { "0": {}, "1": {} } 
}

注:{}代表文件对象

现有前端React提交代码

const handleSubmit = async (event) => {
    event.preventDefault();

    const products = new FormData();

    Object.keys(p_details).forEach((key) => products.append(key, p_details[key]));

    // Iterate over the Image object and append each file
    var parentObj = [];

    for (var key in p_imgs.Image) {
        if (p_imgs.Image.hasOwnProperty(key)) {
            var file = p_imgs.Image[key];
            var nameWithKey = p_imgs.Name + "[" + key + "]";
            var obj = {
                "Name": nameWithKey,
                "user": 2,
                "image": file,
                "secret_key": "Keys"
            };
            parentObj.push(obj);
        }
    }
    products.append('product_image', JSON.stringify(parentObj));
   

    try {
        const response = await fetch('http://127.0.0.1:8000/media/product/create/', {
            method: 'POST',
            body: products
        });
        
        if (!response.ok) {
            const errorMessage = await response.text();
            throw new Error(`Server error: ${response.status} - ${errorMessage}`);
        }

        console.log('File uploaded successfully.', response);
    } catch (error) {
        console.error('Error uploading file:', error);
        console.error('Error uploading file:', error.response?.data);
    }        
};

后端Django Serializer代码

class ProductSerializer(serializers.ModelSerializer):
    product_image = ProductImageSerializer(many=True)

    class Meta:
         model = ProductSize
         fields = "__all__"

解决方案

问题根源

将product_image数组序列化为JSON字符串后append到FormData,Django的嵌套序列化器(带many=True)无法解析字符串格式的列表,且列表中包含文件对象,不能通过JSON传递。

修正后的前端代码

采用Django REST Framework支持的FormData嵌套列表命名规则,将每个product_image对象的字段单独append,格式为product_image[index].field_name:

const handleSubmit = async (event) => {
    event.preventDefault();

    const products = new FormData();

    // 处理基础字段
    Object.keys(p_details).forEach((key) => {
        // 布尔值转字符串,避免FormData自动转换问题
        const value = typeof p_details[key] === 'boolean' ? p_details[key].toString() : p_details[key];
        products.append(key, value);
    });

    // 处理product_image列表
    let imgIndex = 0;
    for (const key in p_imgs.Image) {
        if (p_imgs.Image.hasOwnProperty(key)) {
            const file = p_imgs.Image[key];
            const nameWithKey = `${p_imgs.Name}[${key}]`;
            
            // 按嵌套列表规则逐个append字段
            products.append(`product_image[${imgIndex}].Name`, nameWithKey);
            products.append(`product_image[${imgIndex}].user`, 2);
            products.append(`product_image[${imgIndex}].image`, file);
            products.append(`product_image[${imgIndex}].secret_key`, "Keys");
            
            imgIndex++;
        }
    }

    try {
        const response = await fetch('http://127.0.0.1:8000/media/product/create/', {
            method: 'POST',
            body: products
        });
        
        if (!response.ok) {
            const errorMessage = await response.text();
            throw new Error(`Server error: ${response.status} - ${errorMessage}`);
        }

        console.log('File uploaded successfully.', response);
    } catch (error) {
        console.error('Error uploading file:', error);
        console.error('Error uploading file:', error.response?.data);
    }        
};

说明

  • 这种命名方式是DRF处理FormData中嵌套对象列表的标准格式,序列化器会自动将这些字段组合为对应的对象数组。
  • 文件对象直接通过FormData传递,无需序列化,保证后端能正确解析文件流。
  • 布尔值手动转为字符串,避免FormData将true/false转为"true"/"false"时可能出现的解析问题(Django通常能自动处理,但显式转换更稳妥)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 06:45:57