如何在Django Rest Framework中同时上传文本与文件并解决JSONParser报错
错误根因
当请求中包含文件时,必须使用
multipart/form-data格式编码,你代码中使用的JSONParser仅支持解析application/json格式的纯文本请求体,无法识别二进制文件内容,因此直接抛出解析错误。
修复步骤
1. Django后端视图修改
你原有的POST请求逻辑中的解析逻辑完全不适用于文件上传场景,直接替换为以下两种写法任意一种即可:
写法1:使用DRF自带解析器(推荐)
# views.py from rest_framework.parsers import MultiPartParser, FormParser from rest_framework.decorators import parser_classes @csrf_exempt @parser_classes([MultiPartParser, FormParser]) def ChapterApi(request, id=0): if request.method=='GET': chapters=UploadChapter.objects.all() chaptersSerializer=UploadChapterSerializer(chapters, many=True) return JsonResponse(chaptersSerializer.data, safe=False) elif request.method=='POST': # 解析器会自动将文本字段、文件合并到request.data中,直接传给序列化器即可 chaptersSerializer=UploadChapterSerializer(data=request.data) if chaptersSerializer.is_valid(): chaptersSerializer.save() return JsonResponse('Added Successfully', safe=False) # 新增错误返回,方便排查参数校验问题 return JsonResponse({'msg':'Failed', 'errors': chaptersSerializer.errors}, status=400)
写法2:手动读取请求数据
如果不想引入DRF的解析器装饰器,也可以手动从请求中提取参数:
# views.py POST逻辑替换 elif request.method=='POST': upload_data = { "chapter_number": request.POST.get("chapter_number"), "chapter_file": request.FILES.get("chapter_file"), "student": request.POST.get("student"), "supervisor": request.POST.get("supervisor"), "status": request.POST.get("status", "Pending") } chaptersSerializer=UploadChapterSerializer(data=upload_data) if chaptersSerializer.is_valid(): chaptersSerializer.save() return JsonResponse('Added Successfully', safe=False) return JsonResponse({'msg':'Failed', 'errors': chaptersSerializer.errors}, status=400)
2. Angular前端配置要求
前端请求必须按照以下规则编写,否则后端依然无法解析:
- 所有参数必须封装到
FormData对象中,禁止直接提交JSON对象 - 不要手动设置
Content-Type请求头,浏览器会自动生成带边界标识的multipart/form-data请求头,手动设置会导致边界标识丢失,解析失败
Angular请求示例:
uploadChapter(formValue: any, uploadFile: File) { const formData = new FormData(); // 追加文本参数,key要和后端序列化器字段名一致 formData.append('chapter_number', formValue.chapter_number); formData.append('student', formValue.student_id); formData.append('supervisor', formValue.supervisor_id); // 追加文件参数,key对应序列化器的chapter_file字段 formData.append('chapter_file', uploadFile, uploadFile.name); // 发送请求,不需要手动加Content-Type头 return this.http.post('/你的接口路径', formData); }
可选配置(文件存储必备)
需要在Django项目配置中添加媒体文件配置,否则上传的文件无法正常存储和访问:
settings.py新增配置:
MEDIA_ROOT = BASE_DIR / 'media' MEDIA_URL = '/media/'
- 项目根
urls.py添加静态资源路由(仅开发环境生效):
from django.conf import settings from django.conf.urls.static import static urlpatterns = [ # 原有其他路由 ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
内容的提问来源于stack exchange,提问作者Buhari Ahmed Alhassan
相关产品推荐
相关产品推荐

