如何用React Native向Django服务器上传含图片的表单?
问题修复方案
核心问题:你当前通过JSON传递图片本地路径,但Django的ImageField要求接收**multipart/form-data格式的二进制文件**,而非字符串路径。以下是前后端的具体修复步骤:
一、前端React Native代码修改
1. 重构请求体为FormData
将普通字段和图片文件统一用FormData包裹,图片需以二进制资源形式添加,复杂JSON结构转为字符串传递:
const { Name, bio, displayFilePath, backgroundFilePath } = this.props.route.params.stepOneData; // 提取ImagePicker返回的图片核心信息 const displayAsset = displayFilePath.assets[0]; const backgroundAsset = backgroundFilePath.assets[0]; // 处理Android端file://前缀,转为本地真实路径 const getLocalFilePath = (uri) => { return uri.startsWith('file://') ? uri.slice(7) : uri; }; const formData = new FormData(); // 添加details下的文本字段 formData.append('details[name]', Name); formData.append('details[description]', bio); // 添加display图片文件 formData.append('details[display]', { uri: getLocalFilePath(displayAsset.uri), name: displayAsset.fileName, type: displayAsset.type || 'image/jpeg', // 兜底设置图片MIME类型 }); // 添加background图片文件 formData.append('details[background]', { uri: getLocalFilePath(backgroundAsset.uri), name: backgroundAsset.fileName, type: backgroundAsset.type || 'image/jpeg', }); // 处理hours数组(复杂结构转为JSON字符串) formData.append('hours', JSON.stringify([ { "partition":"P1", "timings":[{ "day":"Monday", "full_day":false, "close_day":false, "start_time":"2022-09-16T01:00:00.149Z", "close_time":"2022-09-16T01:00:00.149Z" }] } ])); try { await addNewGroundAPI(formData); alert("Post created"); } catch (e) { console.log("Error", e); }
2. 调整API请求配置
不要手动设置Content-Type,让请求库自动生成带boundary的multipart/form-data头(以axios为例):
const addNewGroundAPI = async (formData) => { return await axios.post('/api/grounds/', formData, { headers: { // 注释手动设置,axios会自动处理FormData的请求头 // 'Content-Type': 'multipart/form-data', }, }); };
二、后端Django代码调整
1. 序列化器适配
确保序列化器的文件字段为ImageField,并支持嵌套结构解析:
from rest_framework import serializers class TimingsSerializer(serializers.Serializer): day = serializers.CharField() full_day = serializers.BooleanField() close_day = serializers.BooleanField() start_time = serializers.DateTimeField() close_time = serializers.DateTimeField() class HoursSerializer(serializers.Serializer): partition = serializers.CharField() timings = TimingsSerializer(many=True) class DetailsSerializer(serializers.Serializer): name = serializers.CharField() description = serializers.CharField() display = serializers.ImageField() background = serializers.ImageField() class GroundSerializer(serializers.Serializer): details = DetailsSerializer() hours = HoursSerializer(many=True)
2. 视图层解析FormData
手动解析JSON字符串字段,构建序列化器所需的数据结构:
from rest_framework.views import APIView from rest_framework.response import Response import json class AddGroundView(APIView): def post(self, request): try: # 解析hours的JSON字符串 hours_data = json.loads(request.data.get('hours')) # 组装完整请求数据 payload = { 'details': { 'name': request.data['details[name]'], 'description': request.data['details[description]'], 'display': request.data['details[display]'], 'background': request.data['details[background]'], }, 'hours': hours_data } serializer = GroundSerializer(data=payload) if serializer.is_valid(): # 此处添加模型保存逻辑,示例: # Ground.objects.create( # name=payload['details']['name'], # description=payload['details']['description'], # display=payload['details']['display'], # background=payload['details']['background'] # ) return Response({'status': 'success'}, status=201) return Response(serializer.errors, status=400) except json.JSONDecodeError: return Response({'error': 'Invalid hours data'}, status=400)
3. 基础配置检查
确保Django开启文件上传支持:
# settings.py MEDIA_ROOT = BASE_DIR / 'media' MEDIA_URL = '/media/'
内容的提问来源于stack exchange,提问作者Ahmed Yasin
相关产品推荐
相关产品推荐

