Django POST上传Excel触发MultiValueDictKeyError('excel_file')报错
报错根因
django.utils.datastructures.MultiValueDictKeyError: 'excel_file' 代表请求携带的文件集合中不存在键名为excel_file的文件,结合贴出的代码,触发问题的原因按优先级排序如下:
- 代码缩进错误:
post方法顶格编写,没有缩进在FileView类内部,类上配置的MultiPartParser、FormParser根本没有绑定到视图逻辑,DRF不会按文件上传格式解析请求,自然无法从request.FILES中拿到内容 - 前后端字段名不匹配:前端上传文件时,表单项的
name属性值不是excel_file,和后端取数的key不一致 - 请求格式错误:前端发请求时没有使用
multipart/form-data格式传输,或手动设置Content-Type请求头丢失了boundary边界标识,导致文件无法被正常解析
修复方案
- 修正代码缩进问题,将
post方法纳入FileView类的作用域,同时优化文件获取逻辑,避免直接抛KeyError导致500异常:
import openpyxl from rest_framework.views import APIView from rest_framework.parsers import MultiPartParser, FormParser from rest_framework.permissions import IsAdminUser from rest_framework.response import Response from rest_framework import status class FileView(APIView): parser_classes = (MultiPartParser, FormParser) permission_classes = [IsAdminUser] # 注意此处必须缩进4个空格,属于类的实例方法 def post(self, request, *args, **kwargs): ''' 医院入院数据Excel批量导入接口 ''' # 用get方法取文件,不存在则返回友好的400提示 excel_file = request.FILES.get("excel_file") if not excel_file: return Response( {'err_msg': '未检测到上传的Excel文件,请确认上传字段名为excel_file'}, status=status.HTTP_400_BAD_REQUEST ) # 校验文件格式,避免非预期文件导致解析失败 if not excel_file.name.endswith('.xlsx'): return Response( {'err_msg': '仅支持.xlsx格式的Excel文件,旧版.xls请转换后上传'}, status=status.HTTP_400_BAD_REQUEST ) wb = openpyxl.load_workbook(excel_file, data_only=True) worksheet = wb['Sheet1'] # 后续数据读取、入库逻辑在此处编写
- 检查前端上传配置:
- 上传控件的
name属性必须设置为excel_file,和后端取数的key完全一致 - 不要手动设置
Content-Type请求头,让浏览器自动生成带boundary标识的multipart/form-data头,手动设置会导致服务端解析失败
- 上传控件的
- 接口调试注意事项:
- 用Postman等工具调试时,选择
form-data请求类型,新增File类型的字段,字段名填写excel_file后再选择本地文件上传,不要使用raw、x-www-form-urlencoded等请求类型
- 用Postman等工具调试时,选择
额外避坑提示
- 代码注释标注接口支持xls文件,但
openpyxl库仅支持解析.xlsx格式,若需要兼容旧版.xls格式,需安装1.2.0版本的xlrd库做解析,高版本xlrd已移除xls格式支持 - 直接用下标
request.FILES["excel_file"]取值的方式鲁棒性差,一旦请求参数不符合预期就会抛出500服务端错误,统一用get()方法取值后做参数校验,返回对应400状态码更符合RESTful接口规范
内容的提问来源于stack exchange,提问作者mayank gupta
相关产品推荐
相关产品推荐

