3
votes

I'm trying to create a view for uploading a .csv file and parsing it on the template but it's returning a

MultiValueDictKeyError at /

'file'

The template has


<form method="POST" enctype="multipart/form-data">{% csrf_token %}
<div class="file-field input-field">
<div class="btn">
<span>Upload a CSV FILE</span>
<input type="file" name="file">
</div>
<div class="file-path-wrapper">
 <input class="file-path validate" type="text">
</div>
<button class="waves-effect waves-light btn teal" type="submit">Upload</button>
</div>
</form>

Then my views has

import csv, io
from django.shortcuts import render
from django.contrib import messages

def data_upload(request):
    template = "home.html"

    if request.method == 'GET':
        return render(request, template)

    csv_file = request.FILES['file']
    if not csv_file.name.endswith('.csv'):
        messages.error(request, 'Please upload a .csv file.')

    data_set = csv_file.read().decode('UTF-8')
    io_string = io.StringIO(data_set)
    next(io_string)
    for column in csv.reader(io_string, delimiter=',', quoteschar="|"):
        _, created = Table.objects.update_or_create(
            page=column[0], 
            keyword=column[1], 
            interval=column[2], 
            email=column[3], 
            billing=column[4], 
            notes=column[5],
        )
    context = {}
    return render(request, template, context)

I'm wondering why it's returning the error(?).

3
You should upload this file with multipart/form-data header.Sahil
@Sahil I don't know if you missed it but it is already on the template above even before you commentedhighcenbug
Sorry about that, my bad.Sahil
you need to add condition for get and post method. If request.method == "GET" render page else check request.FILES["file"]Nalin Dobhal

3 Answers

1
votes

I added

if request.method == 'GET':
        return render(request, template)

and it ran successfully

0
votes

@highcenbug Still there is one correction is there in your views.py file. you need to use quotechar.

   for column in csv.reader(io_string, delimiter=',', quotechar="|"):
0
votes

This is the real meaning of this MultiValueDictKeyError (picked from the Django documentation itself):

QueryDict.__getitem__(key)
Returns the value for the given key. If the key has more than one value, it returns the last value. Raises django.
utils.datastructures.MultiValueDictKeyError if the key does not exist. (This is a subclass of
Python’s standard KeyError, so you can stick to catching KeyError.) 

Simply put, what this means is that the django system says that they key value you are mentioing in your code does not exist.

And this is a portion of code from datastructures.py file in /home/user/.virtualenvs/you_virtual_envirenment_name/lib/python3.8/site-packages/django/utils/datastructures.py:

def __getitem__(self, key):
        """
        Return the last data value for this key, or [] if it's an empty list;
        raise KeyError if not found.
        """
        try:
            list_ = super().__getitem__(key)
        except KeyError:
            raise MultiValueDictKeyError(key)
        try:
            return list_[-1]
        except IndexError:
            return []

The above method is the getitem method for dictionary key in datastructures.py

Reference:

Django Documentation PDF version Chapter 6 API Reference, page 1326.

I do not quite remember how i downloaded it, but i went to the official documentation site and there was an option to download as pdf

thank you for reading my answer.

https://docs.djangoproject.com/en/3.1/