将文件发送到 django 时出现 Keyerror/MultiValueDictKeyError

Posted

技术标签:

【中文标题】将文件发送到 django 时出现 Keyerror/MultiValueDictKeyError【英文标题】:Keyerror/MultiValueDictKeyError while sending file to django 【发布时间】:2020-08-28 08:31:39 【问题描述】:

我将表单数据发送到 django api,表单数据也包含文件。当我通过 AJAX 将数据发送到 django 时,MultiValueDict 为 空,我得到文件的 KeyError。我在没有发送文件的情况下进行了测试,但当我发送文件时它不起作用。

index.html [前端]

<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal" style="background-color:#00d1b2;border-color: transparent;color: #fff;font-size:20px;font-family:sans-serif;">Create Auto-Label Project</button>
<div class="modal" id="myModal" >
    <div class="modal-background"></div>
        <div class="modal-card" style="width:800px;">
        <header class="modal-card-head">
            <p class="modal-card-title">Create Auot-Label Project</p>
            <button type="button" aria-label="close" class="delete" data-dismiss="modal">&times;</button>

        </header>

        <section class="modal-card-body">

        <form  method="POST" id="upload" name="upload"  action="http://API_LINK">
            <div class="field">
               <label class="label">Project Name</label>
               <div class="control">
                   <input type="text" name="project_name" id="project_name" required="required" placeholder="Project name" class="input">

                </div>

                <p class="help is-danger"></p>

            </div>

            <div class="field">
                <label class="label">Description</label>
                <div class="control">
                    <textarea name="description" id="description" required="required" placeholder="Project description" class="textarea"></textarea>

                </div>

                <p class="help is-danger"></p>

            </div>

            <div class="field">
                <label class="label">Project Type</label>
                <div class="control">
                    <select name="project_type" id="project_type" required="required">
                        <option value="" selected="selected">---------</option>
                        <option value="DocumentClassification">document classification</option>
                        <option value="SequenceLabeling">sequence labeling</option>
                        <option value="Seq2seq">sequence to sequence</option>

                    </select>

                </div>

                <p class="help is-danger"></p>

            </div>

            <div class="field">
                <label class="label">Model Type</label>
                <div class="control">
                    <select name="model_name" id="model_name" required="required">
                        <option value="" selected="selected">---------</option>
                        <option value="sn">Simple NER</option>
                        <option value="mn">Bio-NER</option>
                        <option value="sa">Sentiment Analysis</option>
                    </select>

                </div>

                <p class="help is-danger"></p>

            </div>
            <div class="field">
                <label class="label">Guideline</label>
                <div class="control">
                    <textarea name="guideline" id="guideline" required="required" placeholder="Project guideline" class="textarea"></textarea>
                </div>

                <p class="help is-danger"></p>

            </div>

            <div class="field">
                <label class="label">Upload File</label>
                <div class="control">
                    <input type="file" required="required" id="file" name="myfile"  enctype="multipart/form-data" /><br><br>
                </div>
            </div>
            <div class="field">
               <label class="label">Confirm User Name</label>
               <div class="control">
                   <input type="text" name="username" id="username" required="required" placeholder="User Name" class="input">
              </div>
          </div>
          <div class="field">
              <label class="label">Confirm Password</label>
              <div class="control">
                  <input type="password" name="password" id="password" required="required" placeholder="Password" class="input">
              </div>
          </div>

          <footer class="modal-card-foot pt20 pb20 pr20 pl20 has-background-white-ter">
                <button type="submit" class="btn btn-success">Create <span class="fa fa-arrow-right"></span></button>
                <button class="button" data-dismiss="modal">Cancel</button>

          </footer>

      </form>

      </section>
    </div>

</div>

<script>
    $(document).ready(function() 
        $('form').submit(function(event) 
            var formData = 
                'project_name': $('input[name=project_name]').val(),
                'project_type': $('select[name=project_type]').val(),
                'guideline': $('textarea[name=guideline]').val(),
                'description': $('textarea[name=description]').val(),
                'model_name': $('select[name=model_name]').val(),
                'username': $('input[name=username]').val(),
                'password': $('input[name=password]').val(),
                'myfile': $('input[name=myfile]').val(),
        ;

        $.ajax(
            type: 'POST',
            url: API_LINK,
            data: formData,
            crossDomain: true,
            dataType: 'json',
            encode: true

        ).done(function(data) 
                console.log(data); 
        );
        event.preventDefault();
    );
);
</script>

views.py [Django API 视图]

@csrf_exempt
def post_auto_label(request):
    if request.method == 'POST':
        print(request.FILES)
        myfile = request.FILES['myfile']
        project_name = request.POST.get('project_name')
        project_type = request.POST.get('project_type')
        guideline = request.POST.get('guideline')
        description = request.POST.get('description')
        model_name = request.POST.get('model_name')
        username = request.POST.get('username')
        password = request.POST.get('password')

        fs=FileSystemStorage()
        filename = fs.save(myfile.name, myfile)
        file_path = os.path.abspath("media/"+filename)

        if check_project_exist_or_not(username, password, project_name):
            print("Project already exist")
            if upload_labeled_data(username, password, project_name, model_name, 
                                file_path):
                return JsonResponse("status": "Project created successfully.")
            else:
                return JsonResponse("status": "Project can't be created. \
                Either you're not authenticated to create project or check the \
                file you are trying to upload.")

        else:
            if project_creation(username, password, project_name, description, 
        project_type, guideline):
                print("created project....")
                if upload_labeled_data(username, password, project_name, model_name, 
                                file_path):
                    return JsonResponse("status": "Project created successfully.")
                else:
                    return JsonResponse("status": "Project can't be created. Either \
                    you're not authenticated to create project or check the file you \
                    are trying to upload.")
            else:
                return JsonResponse("status": "Project failed to create, check \
                username or password")

在后端 Django 显示以下错误:

KeyError: 'myfile'
During handling of the above exception, another exception occurred:
django.utils.datastructures.MultiValueDictKeyError: 'myfile'

在前端

failed to load resource: the server respond with a status of 500

我的formdata在console.log()中显示如下

Object
description: "jlsfj",
guideline: "jfslfsjlow",
model_name: "sn",
myfile: "C:\fakepath\file.txt",
password: "password"
project_name: "name",
project_type: "lfsjl",
username: "user"

【问题讨论】:

【参考方案1】:

您应该将enctype="multipart/form-data" 放在&lt;form&gt; 标记中,而不是&lt;input&gt; 标记中。

<form method="post" enctype="multipart/form-data" ....>

也不要错过安装django-cors-headers

pip install django-cors-headers

然后将其添加到您安装的应用程序中:

INSTALLED_APPS = [
    ...
    'corsheaders',
    ...
]


MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ....
]

CORS_ORIGIN_ALLOW_ALL = True

【讨论】:

我尝试将enctype="multipart/form-data" 放入&lt;form&gt; 并从&lt;input&gt; 中删除,但它在后端和前端console.log 中显示相同的错误Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at API_LINK跨度> @Alok 不要错过更改为您的网址 action="http://API_LINK" => 我认为该网址无效。 我通过 Postman 测试了 api 是否正常,API_LINK 是正确的,和我在 postman 中使用的一样。 我已经添加了这个库来避免 cors 问题,现在 cors 问题消失了,但 KeyError 仍然存在。 @Alok 和print(request.FILES) 的打印输出是什么?

以上是关于将文件发送到 django 时出现 Keyerror/MultiValueDictKeyError的主要内容,如果未能解决你的问题,请参考以下文章

在 django 项目中删除文件时出现 403 FORBIDDEN

发送 ajax 请求 django 时出现 400 错误

尝试向 API 发送 POST 请求时出现属性错误 - Django

尝试使用 Django 发送电子邮件时出现“[Errno 101] 网络无法访问”

从 React 向 Django 发送 post 请求时出现 400(错误请求)

尝试在 AWS Beanstalk 上运行 django 项目时出现实例配置文件不存在的错误