使用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
相关产品推荐
相关产品推荐

