Django+Ajax表单上传图片出现KeyError: 'file'错误求助
Django结合Ajax上传图片出现
KeyError: 'file'问题排查与解决 问题描述
使用Django配合Ajax实现带图片的表单上传功能,通过POST请求提交数据时,后端始终抛出KeyError: 'file'(实际报错为django.utils.datastructures.MultiValueDictKeyError: 'file')。
相关代码
HTML表单
<form id="addProduct" method="post" enctype="multipart/form-data"> <label class="form-label required-field" for="file">图片</label> <input class='form-control' id='file' name="file" type="file" accept="image/*" required/> </form>
JavaScript代码
$("#addProduct").on("submit", function (e) { e.preventDefault() var data = new FormData(this); $.ajax({ url: '/admin/product/add/', data: data, type: 'post', success: function (response) { var result = response.result console.log(result) if (result == false) { alert("添加产品失败") } else { alert("添加产品成功") } }, cache: false, contentType: false, processData: false }) }
Django视图代码
class ProductAddPage(View): def post(self, request): img = request.FILES['file'] try: # 后续处理逻辑 except: traceback.print_exc() return JsonResponse({"result":False}, status=200, safe=False) return JsonResponse({"result":True}, status=200, safe=False)
报错栈信息
Internal Server Error: /admin/product/add/ Traceback (most recent call last): File "D:\Codes\Django\env\lib\site-packages\django\utils\datastructures.py", line 84, in __getitem__ list_ = super().__getitem__(key) KeyError: 'file' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "D:\Codes\Django\env\lib\site-packages\django\core\handlers\exception.py", line 55, in inner response = get_response(request) File "D:\Codes\Django\env\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "D:\Codes\Django\env\lib\site-packages\django\views\generic\base.py", line 103, in view return self.dispatch(request, *args, **kwargs) File "D:\Codes\Django\env\lib\site-packages\django\contrib\auth\mixins.py", line 73, in dispatch return super().dispatch(request, *args, **kwargs) File "D:\Codes\Django\env\lib\site-packages\django\views\generic\base.py", line 142, in dispatch return handler(request, *args, **kwargs) File "D:\Codes\Django\draft\admin\views.py", line 346, in post img = request.FILES['file'] File "D:\Codes\Django\env\lib\site-packages\django\utils\datastructures.py", line 86, in __getitem__ raise MultiValueDictKeyError(key) django.utils.datastructures.MultiValueDictKeyError: 'file'
解决步骤
修复JavaScript语法错误
原JS代码最后缺少闭合的),导致代码无法执行,表单可能默认提交(跳过Ajax逻辑),文件未被正确传递。修复后的代码:$("#addProduct").on("submit", function (e) { e.preventDefault() var data = new FormData(this); // 可选:打印文件对象验证是否捕获成功 console.log(data.get('file')); $.ajax({ url: '/admin/product/add/', data: data, type: 'post', success: function (response) { var result = response.result console.log(result) alert(result ? "添加产品成功" : "添加产品失败") }, cache: false, contentType: false, processData: false }) }); // 补上闭合括号与分号验证CSRF令牌传递
Django默认启用CSRF保护,Ajax请求需携带CSRF令牌:- 方式1:在HTML表单中添加
{% csrf_token %},FormData会自动包含该字段 - 方式2:在Ajax请求中手动添加headers:
headers: { 'X-CSRFToken': $('input[name="csrfmiddlewaretoken"]').val() },
- 方式1:在HTML表单中添加
增加后端容错与调试
修改视图代码,先判断文件是否存在,同时打印请求数据排查问题:class ProductAddPage(View): def post(self, request): # 打印请求数据用于调试 print("接收的FILES:", request.FILES) print("接收的POST数据:", request.POST) if 'file' not in request.FILES: return JsonResponse({"result":False, "msg":"未上传文件"}, status=400, safe=False) img = request.FILES['file'] try: // 后续处理逻辑 except Exception as e: traceback.print_exc() return JsonResponse({"result":False}, status=200, safe=False) return JsonResponse({"result":True}, status=200, safe=False)确认表单元素有效性
检查input的name属性是否确实为file,页面中是否存在重复的id="addProduct"元素,确保FormData能正确捕获表单内容。
内容的提问来源于stack exchange,提问作者Trương Xuân Dũng
相关产品推荐
相关产品推荐

