如何从React Native向Django上传图片并传输多字段表单数据
要实现把表单数据、图片、姓名邮箱传到Django后端,分前端React Native和后端Django两部分来搞:
前端React Native实现步骤
1. 安装图片选择依赖
用react-native-image-picker实现图片选择,执行安装命令:
npm install react-native-image-picker --save # 或用yarn yarn add react-native-image-picker
然后配置平台权限:
- iOS:在
Info.plist添加相册/相机权限:<key>NSPhotoLibraryUsageDescription</key> <string>需要访问相册选择图片</string> <key>NSCameraUsageDescription</key> <string>需要访问相机拍摄图片</string> - Android:在
AndroidManifest.xml添加权限:<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.CAMERA" />
2. 补全组件状态与UI
在你的add_post组件里补充姓名、邮箱、图片状态,添加对应输入框和操作按钮:
import React, { useState } from 'react'; import { View, Text, ScrollView, StyleSheet, ImageBackground, TouchableOpacity } from 'react-native'; import { TextInput } from 'react-native-paper'; import { launchImageLibrary } from 'react-native-image-picker'; const add_post = () => { // 原有状态 const [city, setcity] = useState(''); const [carinfo, setcarinfo] = useState(''); const [milage, setmilage] = useState(''); const [price, setprice] = useState(''); const [company, setcompany] = useState(''); // 新增状态 const [name, setName] = useState(''); const [email, setEmail] = useState(''); const [selectedImages, setSelectedImages] = useState([]); // 图片选择逻辑 const pickImages = () => { const options = { mediaType: 'photo', maxWidth: 1000, maxHeight: 1000, quality: 0.8, selectionLimit: 5, // 最多选5张,可调整 }; launchImageLibrary(options, (response) => { if (response.didCancel) return; if (response.errorCode) { console.log('图片选择出错:', response.errorMessage); return; } setSelectedImages([...selectedImages, ...response.assets]); }); }; // 提交数据逻辑 const submitData = async () => { const formData = new FormData(); // 追加表单字段 formData.append('name', name); formData.append('email', email); formData.append('city', city); formData.append('car_info', carinfo); formData.append('milage', milage); formData.append('price', price); formData.append('company', company); // 追加图片,后端用数组接收,字段名带[] selectedImages.forEach((image, index) => { formData.append('images[]', { uri: image.uri, type: image.type, name: `car_image_${index}.jpg`, }); }); try { const response = await fetch('http://你的Django服务器IP:端口/api/car-post/', { method: 'POST', body: formData, // fetch会自动处理multipart/form-data的Content-Type,无需手动设置 }); if (response.ok) { const result = await response.json(); console.log('提交成功:', result); // 可添加清空表单等后续逻辑 } else { const error = await response.json(); console.log('提交失败:', error); } } catch (err) { console.log('网络错误:', err); } }; return ( <ScrollView> {/* 保留你原有的步骤指示器代码 */} <ImageBackground> {/* ... 你的原有代码 ... */} </ImageBackground> <View style={{backgroundColor:'green', width:'100%', marginTop:120, paddingBottom:20}}> <Text style={{alignSelf:'center', fontSize:25, color:'white', marginVertical:10}}> Car Information </Text> {/* 新增姓名输入框 */} <TextInput style={styles.inputstyle} label="姓名" value={name} mode="outlined" onChangeText={Text => setName(Text)} /> {/* 新增邮箱输入框 */} <TextInput style={styles.inputstyle} label="邮箱" value={email} mode="outlined" onChangeText={Text => setEmail(Text)} /> {/* 原有输入框,保留 */} <TextInput style={styles.inputstyle} label="City" value={city} mode="outlined" onChangeText={Text => setcity(Text)} /> <TextInput style={styles.inputstyle} label="Car Information" value={carinfo} mode="outlined" onChangeText={Text => setcarinfo(Text)} /> <TextInput style={styles.inputstyle} label="Milage" value={milage} mode="outlined" onChangeText={Text => setmilage(Text)} /> <TextInput style={styles.inputstyle} label="Price" value={price} mode="outlined" onChangeText={Text => setprice(Text)} /> <TextInput style={styles.inputstyle} label="Company" value={company} mode="outlined" onChangeText={Text => setcompany(Text)} /> {/* 图片选择按钮 */} <TouchableOpacity style={{ backgroundColor: '#fff', padding: 10, borderRadius: 5, alignSelf: 'center', marginVertical: 15, }} onPress={pickImages} > <Text style={{color: 'green', fontSize: 16}}>选择图片</Text> </TouchableOpacity> {/* 提交按钮 */} <TouchableOpacity style={{ backgroundColor: '#fff', padding: 15, borderRadius: 5, alignSelf: 'center', width: '80%', }} onPress={submitData} > <Text style={{color: 'green', fontSize: 18, textAlign: 'center'}}>提交信息</Text> </TouchableOpacity> </View> </ScrollView> ); }; const styles = StyleSheet.create({ inputstyle:{ marginTop:15, width:200, alignSelf:'center', } }); export default add_post;
后端Django实现步骤
1. 配置媒体文件与跨域
先安装跨域处理包:
pip install django-cors-headers
在settings.py中配置:
INSTALLED_APPS = [ # ... 其他内置app 'corsheaders', 'rest_framework', ] MIDDLEWARE = [ # ... 其他中间件 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', ] # 允许跨域的源,根据RN调试地址调整 CORS_ALLOWED_ORIGINS = [ "http://localhost:8081", "http://192.168.x.x:8081", # 真机调试的本地IP ] # 媒体文件存储配置 MEDIA_ROOT = BASE_DIR / 'media' MEDIA_URL = '/media/'
在项目根目录urls.py挂载媒体路由:
from django.conf import settings from django.conf.urls.static import static from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('你的app名称.urls')), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
2. 创建数据模型
在你的app的models.py中定义模型:
from django.db import models class CarPost(models.Model): name = models.CharField(max_length=100) email = models.EmailField() city = models.CharField(max_length=100) car_info = models.TextField() milage = models.CharField(max_length=20) price = models.DecimalField(max_digits=10, decimal_places=2) company = models.CharField(max_length=100) images = models.ManyToManyField('CarImage', related_name='car_posts') class CarImage(models.Model): image = models.ImageField(upload_to='car_images/%Y/%m/%d/') uploaded_at = models.DateTimeField(auto_now_add=True)
执行数据库迁移:
python manage.py makemigrations python manage.py migrate
3. 编写接收请求的视图
在app的views.py中编写视图:
from django.http import JsonResponse from rest_framework.decorators import api_view from .models import CarPost, CarImage from django.core.files.uploadedfile import UploadedFile @api_view(['POST']) def create_car_post(request): try: # 提取表单数据 name = request.data.get('name') email = request.data.get('email') city = request.data.get('city') car_info = request.data.get('car_info') milage = request.data.get('milage') price = request.data.get('price') company = request.data.get('company') # 创建汽车帖子实例 car_post = CarPost.objects.create( name=name, email=email, city=city, car_info=car_info, milage=milage, price=price, company=company ) # 处理上传的图片 images = request.FILES.getlist('images[]') for image in images: if isinstance(image, UploadedFile): car_image = CarImage.objects.create(image=image) car_post.images.add(car_image) return JsonResponse({ 'status': 'success', 'message': '汽车信息提交成功', 'data': {'id': car_post.id, 'name': car_post.name} }, status=201) except Exception as e: return JsonResponse({ 'status': 'error', 'message': str(e) }, status=400)
4. 配置路由
在app目录下新建urls.py,配置路由:
from django.urls import path from .views import create_car_post urlpatterns = [ path('car-post/', create_car_post, name='create_car_post'), ]
最后启动Django服务器,确保RN和Django在同一局域网内(真机调试时),即可测试提交功能。
内容的提问来源于stack exchange,提问作者Android games
相关产品推荐
相关产品推荐

