Search code examples
htmldjangoformsdjango-viewsdjango-templates

CSV file not coming through on submission of html form via POST method (in the context of using Django)


I am building a very simple application which includes one page where a user submits a list of zip codes and then is returned a file with zip codes in a certain radius of the original list.

My problem is that my function for processing the file that is contained in the views.py file is not able to retrieve the '.csv' file after the post form. The FILES metadata on the request is missing and I cannot figure out why. More details below:

Error I am seeing:

Internal Server Error: /zip_app/
Traceback (most recent call last):
  File "/home/louis/.cache/pypoetry/virtualenvs/zip-radius-app-1xSGHScf-py3.10/lib/python3.10/site-packages/django/utils/datastructures.py", line 84, in __getitem__
    list_ = super().__getitem__(key)
KeyError: 'csvFile'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/louis/.cache/pypoetry/virtualenvs/zip-radius-app-1xSGHScf-py3.10/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/louis/.cache/pypoetry/virtualenvs/zip-radius-app-1xSGHScf-py3.10/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/louis/.cache/pypoetry/virtualenvs/zip-radius-app-1xSGHScf-py3.10/lib/python3.10/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
    return view_func(request, *args, **kwargs)
  File "/home/louis/Documents/github/zip_radius_tool/zip_radius_app/zip_app/views.py", line 30, in index
    f = request.FILES['csvFile']
  File "/home/louis/.cache/pypoetry/virtualenvs/zip-radius-app-1xSGHScf-py3.10/lib/python3.10/site-packages/django/utils/datastructures.py", line 86, in __getitem__
    raise MultiValueDictKeyError(key)
django.utils.datastructures.MultiValueDictKeyError: 'csvFile'

HTML for the index page where the user submits the .csv file:

<!DOCTYPE html>
<html lang="en">
<head>
<title>W3.CSS Template</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
body {font-family: "Lato", sans-serif}
.mySlides {display: none}
</style>
</head>
<body>

<!-- Page content -->
<div class="w3-content" style="max-width:2000px;margin-top:46px">

  
  <!-- The Band Section -->
  <div class="w3-container w3-content w3-center w3-padding-64" style="max-width:800px" id="band">       
        <form action="" method="post">
          <input type="file" name="csvFile" accept=".csv" enctype="multipart/form-data">
          <button type="submit" formmethod="post">Submit using POST</button>
        </form>
  </div>
  
<!-- End Page Content -->
</div>

</body>
</html>

And my views.py file (the 'index' function is getting properly called but is failing on 'f.request.FILES['csvFile']'):

from django.shortcuts import render
from uszipcode import SearchEngine
import pandas as pd
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
# Create your views here.
def index(request):
    context = {}
    if request.method == 'POST':
        d = request.POST
        print(d)
        f = request.FILES['csvFile']
        print(type(f))
        radius_results = pull_radius_zips(f)
        print('checking this works to this point')
    return render(request, "zip_app/index.html", context)

At first I thought i might be an issue with redirecting to the same view on submission of the form but I found this is actually a standard thing to do. Moreover, the index view properly catches when the submission is POST.

I am also seeing that the request.POST properly populates with the name of my test file ('zip_codes.csv') as the value and under the variable 'csvFile', so somewhere the csv file is being dropped from the request object.

Additional info: I have the csrf token check disabled for this view.


Solution

  • You forgot to use enctype="multipart/form-data in your form. You placed it wrong inside the input.

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

    This is why your form is not processing the file in request. This should solve the issue.