You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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'

解决步骤

  1. 修复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
        })
    }); // 补上闭合括号与分号
    
  2. 验证CSRF令牌传递
    Django默认启用CSRF保护,Ajax请求需携带CSRF令牌:

    • 方式1:在HTML表单中添加{% csrf_token %},FormData会自动包含该字段
    • 方式2:在Ajax请求中手动添加headers:
      headers: {
          'X-CSRFToken': $('input[name="csrfmiddlewaretoken"]').val()
      },
      
  3. 增加后端容错与调试
    修改视图代码,先判断文件是否存在,同时打印请求数据排查问题:

    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)
    
  4. 确认表单元素有效性
    检查input的name属性是否确实为file,页面中是否存在重复的id="addProduct"元素,确保FormData能正确捕获表单内容。

内容的提问来源于stack exchange,提问作者Trương Xuân Dũng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 18:41:04