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

使用react-hook-form嵌套对象提交至Django后端失败问题

问题

我正尝试使用react-hook-form向Django后端发送数据,FormData接口定义如下:

interface FormData {
  title: string;
  // other things
  location: {
    country: string | null;
    city: string | null;
    address: string | null;
  };
}

提交表单后,Django后端收到的数据为:

<QueryDict: {'title': ['CCC'], 'location': ['[object Object]']}>

这导致后端无法正确解析location字段。


补充说明

FormData的控制台日志显示数据格式正确:

{
    "title": "test",
    "location": {
        "country": "Italy",
        "city": "Milan",
        "address": "Via xx sttembre"
    }
}

附上onSubmit()函数代码:

const onSubmit = (data: FieldValues) => {
    const apiClient = new APIClient<FieldValues>("events/");

    apiClient
      .create(formData, { headers: { "Content-Type": "multipart/form-data" } })
      .then((res) => {
        setSuccess(true);
        return res.data;
      })
      .catch((err) => setError(err));
    console.log(data);
  };
解决方案

问题原因

你设置了Content-Type: multipart/form-data,但直接传递了嵌套对象location。当用该Content-Type发送数据时,嵌套对象会被默认转换为字符串[object Object],Django无法解析这种格式。

解决办法

方法1:改用JSON格式发送(无文件上传场景首选)

如果不需要上传文件,直接发送JSON格式即可,修改请求头和数据传递:

const onSubmit = (data: FieldValues) => {
    const apiClient = new APIClient<FieldValues>("events/");

    apiClient
      .create(data, { headers: { "Content-Type": "application/json" } })
      .then((res) => {
        setSuccess(true);
        return res.data;
      })
      .catch((err) => setError(err));
    console.log(data);
  };

Django默认配置的django.middleware.common.CommonMiddleware已支持解析JSON,后端视图可直接通过request.data获取嵌套结构的数据。

方法2:手动构建FormData(适用于需上传文件的场景)

如果必须使用multipart/form-data,需要手动将嵌套对象展开为FormData的键值对:

const onSubmit = (data: FieldValues) => {
    const formData = new FormData();
    // 添加普通字段
    formData.append('title', data.title);
    // 展开嵌套的location对象
    if (data.location) {
        formData.append('location[country]', data.location.country || '');
        formData.append('location[city]', data.location.city || '');
        formData.append('location[address]', data.location.address || '');
    }
    // 其他字段同理添加

    const apiClient = new APIClient<FieldValues>("events/");

    apiClient
      .create(formData) // 无需手动设置Content-Type,浏览器会自动处理
      .then((res) => {
        setSuccess(true);
        return res.data;
      })
      .catch((err) => setError(err));
    console.log(data);
  };

Django会自动将location[country]这类键解析为嵌套字典,后端可通过request.POST.get('location[country]')获取对应值,使用Django REST Framework时会直接解析为嵌套对象。

方法3:将嵌套对象转为JSON字符串传递

提交前把location转为JSON字符串,后端再解析:

const onSubmit = (data: FieldValues) => {
    const submitData = {
        ...data,
        location: JSON.stringify(data.location)
    };
    const formData = new FormData();
    Object.entries(submitData).forEach(([key, value]) => {
        formData.append(key, value);
    });

    const apiClient = new APIClient<FieldValues>("events/");

    apiClient
      .create(formData)
      .then((res) => {
        setSuccess(true);
        return res.data;
      })
      .catch((err) => setError(err));
    console.log(data);
  };

后端需要解析JSON字符串:

import json
location_str = request.POST.get('location')
location = json.loads(location_str) if location_str else {}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 23:47:32