1
votes

I’m trying to process files uploaded by the user in Django 2.2 and it appears GET requests are working however POST is throwing MultiValueDictKeyError.

I’m following Vitor Freitas’ glorious Django File Upload Tutorial on YouTube.

At roughly 5 minutes in, the instructor begins adding the POST request method. My project is slightly different in terms of some of the names and other apps I am working with. I am running Django 2.2 in my local dev environment and have no intention of deploying this project in the future.

I've meticulously checked checked every line several times.

When I swap out "POST" for "GET" the MultiValueDictKeyError error disappears and the webpage runs without an error but my Django shell does not print file name and size, as I am expecting.

views.py:

from django.shortcuts import render
from django.views.generic import TemplateView

class Home(TemplateView):
    template_name = "home.html"

def upload(request):
    if request.method == 'POST':
        uploaded_file = request.FILES['document']
        print(uploaded_file.name)
        print(uploaded_file.size)
    return render(request, 'upload.html')

My upload.html:

{% block content %}

    <h1> Eureka! </h1>

    <form method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        <input type="file" name="document">
        <button type="submit">Upload file</button>
    </form>

{% endblock %}

urls.py:

from django.contrib import admin
from django.urls import path, re_path
# from . import views
from posts.views import *
from redactors.views import *
from counters.views import *
from AllAbove.views import *
from django.conf.urls.static import static
from django.conf import settings
from uploads.views import *

urlpatterns = [
   path('admin/', admin.site.urls),
   path('', home, name='home'),
   path('result/', result, name='result'),
   path('seth/', counters, name='seth'),
   path('uploads/', upload, name='upload'),
   #path('james/', post_details, name='james'),
   path('maggie/', maggie_post_details, name='maggie'),
   path('AllAbove/', all_above, name='AllAbove'),
   re_path(r'^posts/(?P<post_id>[0-9]+)/$', post_details, name='james'),
   path('simon/', redactors, name='simon'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + static(settings.STATIC_URL, 

I am expecting the template to prompt the user to upload a file (like an image) and then in the Django shell show the file name and size. Instead, I am receiving the MultiValueDictKeyError. The error indicates there is an issue with the ‘document’ name somewhere. As far as I can tell, 'document' is referenced properly inside both the template and in views.py

Here is the error and traceback in full:

Request Method: POST Request URL: http://127.0.0.1:8000/uploads/ Django Version: 2.2 Exception Type: MultiValueDictKeyError Exception Value:'document' Exception Location: /home//dev/projects/python/2018-and-2019/CC_Redact_Iter2/venv/lib/python3.7/site-packages/django/utils/datastructures.py in getitem, line 80 Python Executable: /home//dev/projects/python/2018-and-2019/CC_Redact_Iter2/venv/bin/python3 Python Version: 3.7.3 Python Path:
['/home//dev/projects/python/2018-and-2019/CC_Redact_Iter2', '/home//dev/projects/python/2018-and-2019/CC_Redact_Iter2/venv/lib/python37.zip', '/home//dev/projects/python/2018-and-2019/CC_Redact_Iter2/venv/lib/python3.7', '/home//dev/projects/python/2018-and-2019/CC_Redact_Iter2/venv/lib/python3.7/lib-dynload', '/usr/lib64/python3.7', '/usr/lib/python3.7', '/home//dev/projects/python/2018-and-2019/CC_Redact_Iter2/venv/lib/python3.7/site-packages'] Server time: Fri, 19 Jul 2019 16:56:46 +0000

And:

$ python3 manage.py runserver Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). July 19, 2019 - 16:57:53 Django version 2.2, using settings 'CC_Redact_Iter2.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C. Internal Server Error: /uploads/ Traceback (most recent call last): File "/home//dev/projects/python/2018-and-2019/CC_Redact_Iter2/venv/lib/python3.7/site-packages/django/utils/datastructures.py", line 78, in getitem list_ = super().getitem(key) KeyError: 'document' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home//dev/projects/python/2018-and-2019/CC_Redact_Iter2/venv/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner response = get_response(request) File "/home//dev/projects/python/2018-and-2019/CC_Redact_Iter2/venv/lib/python3.7/site-packages/django/core/handlers/base.py", line 115, in _get_response response = self.process_exception_by_middleware(e, request) File "/home//dev/projects/python/2018-and-2019/CC_Redact_Iter2/venv/lib/python3.7/site-packages/django/core/handlers/base.py", line 113, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/home//dev/projects/python/2018-and-2019/CC_Redact_Iter2/uploads/views.py", line 9, in upload uploaded_file = request.FILES['document'] File "/home//dev/projects/python/2018-and-2019/CC_Redact_Iter2/venv/lib/python3.7/site-packages/django/utils/datastructures.py", line 80, in getitem raise MultiValueDictKeyError(key) django.utils.datastructures.MultiValueDictKeyError: 'document' [19/Jul/2019 16:57:57] "POST /uploads/ HTTP/1.1" 500 79510

1
Note that request.FILES will only contain data if the request method was POST and the that posted the request has the attribute enctype="multipart/form-data". Otherwise, request.FILES will be empty.BugHunter

1 Answers

2
votes

Just try once using the the MultiValueDict's get() method to get the data from request dictionary.

uploaded_file = request.FILES.get('document', None)