0

I am sending the form data to a django api and the form data includes file also. When I am sending the data to django through AJAX, the MultiValueDict is {} empty and I am getting the KeyError for the file. I tested without sending file it's working but when I send file it's not working.

index.html [Front End]

<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 View]

@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"})

In the backend Django shows the following error:

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

and in the front end

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

my formdata shows as below in 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"
Alok
  • 13
  • 3

1 Answers1

0

You should put the enctype="multipart/form-data" in your <form> tag, not in <input> tag.

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

also don't miss to install django-cors-headers

pip install django-cors-headers

then add it to your installed apps:

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


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

CORS_ORIGIN_ALLOW_ALL = True
binpy
  • 3,994
  • 3
  • 17
  • 54
  • I tried putting `enctype="multipart/form-data"` in `
    ` and removed from the `` but it gives the same error in the backend and in the front end console.log it is showing `Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at API_LINK`
    – Alok May 12 '20 at 13:53
  • @Alok don't miss to change to your url `action="http://API_LINK"` => I think isn't valid url. – binpy May 12 '20 at 13:54
  • I tested the api through Postman it's working and the API_LINK is correct, which is same as I used in the postman. – Alok May 12 '20 at 13:57
  • I already added this library to avoid the cors problem, now the cors problem is gone but still the KeyError persists. – Alok May 12 '20 at 14:20
  • @Alok and what the printout of `print(request.FILES)`? – binpy May 12 '20 at 23:43
  • print(request.FILES) is giving MultiValueDict is {}. – Alok May 13 '20 at 05:26
  • @Alok I think you should follow this answer https://stackoverflow.com/a/20848730/6396981, don't miss to change your `FormData` and `contentType = false` – binpy May 13 '20 at 06:29