Django raises a MultiValueDictKeyError in a file upload

I have already consulted with many forums, and I can not get an answer. I set the file upload in my Django application to save data on my server. But that does not work. Instead, it raises a MultiValueDictKeyError. I think the problem is that request.FILES does not exist (because it causes an error in the request. .FILES mentions), so downloading the file does not work. This is my view.py:

def list_files(request, phase_id): phase = get_object_or_404(Phase, pk=int(phase_id)) if request.method == 'POST': #form = DocumentForm(request.POST, request.FILES) form = DocumentForm(request.POST, request.FILES) if form.is_valid(): newdoc = Document(docfile = request.FILES['docfile'], phase = phase_id) newdoc.save() doc_to_save = request.FILES['docfile'] filename = doc_to_save._get_name() fd = open(settings.MEDIA_URL+'documents/'+str(filename),'wb') for chunk in doc_to_save.chunks(): fd.write(chunk) fd.close() return HttpResponseRedirect(reverse('list_files')) else: form = DocumentForm() documents = Document.objects.filter(phase=phase_id) return render_to_response('teams_test/list_files.html',{'documents': documents, 'form':form, 'phase':phase}, context_instance = RequestContext(request) ) 

Document form in forms.py:

 class DocumentForm(forms.ModelForm): docfile = forms.FileField(label='Select a file', help_text='max. 42 megabytes') class Meta: model = Document 

Class document in models.py:

 class Document(models.Model): docfile = models.FileField(upload_to='documents') phase = models.ForeignKey(Phase) 

Finally, my html code:

 {% extends "layouts/app.html" %} {% load i18n user %} {% block title %}{% trans "Files list" %}{% endblock %} {% block robots %}noindex,nofollow{% endblock %} {% block page%} <div id="page" class="container"> <div class="header prepend-2 span-20 append-2 last whiteboard"> <h2 style="margin-left:-40px">{{ phase.name }} files</h2> {% if documents %} <ul> {% for document in documents %} <li><a href="{{ document.docfile.url }}">{{ document.docfile.name }} {% endfor %} </ul> {% else %} <p>No documents.</p> {% endif %} <form action="{% url list_files phase.id %}" method="post" enctype="multipart/form-data"> {% csrf_token %} <input id="file" type="file" /> <input id="submit" type="submit" value="Upload file" /> </form> </div> </div> {% endblock %} 

My answer says:

 Exception Type: MultiValueDictKeyError Exception Value: "Key 'docfile' not found in <MultiValueDict: {}>" my_dir/views.py in list_files newdoc = Document(docfile = request.FILES['docfile'], phase = phase_id) 

And my QueryDict is empty:

 POST:<QueryDict: {u'csrfmiddlewaretoken': [u'UZSwiLaJ78PqSjwSlh3srGReICzTEWY1']}> 

Why? What am I doing wrong?

Thanks in advance.

+7
django file-upload
source share
2 answers

You need to change multipart/form_data to multipart/form-data - therefore request.FILES empty: the form does not send things in the way Django expects because of a typo. [EDIT: it's already done]

Update 1: Also, instead of directly accessing request.FILES, try relying on the default behavior of the model, since then it will be treated as loading accordingly. those. newdoc = form.save() should do everything you need to take a quick look at it - is there a specific reason why you manually save the file when the model model can do this for you?

Update 2: Ah, look: you are not assigning a name to the file upload element

From the docs:

HttpRequest.FILES A dictionary-like object containing all downloaded files. Each key in FILES is a name from <input type="file" name="" /> . Each value in FILES is an UploadedFile.

So you need to change

 <input id="file" type="file" /> 

in

or, for a standard Django agreement

 <input id="id_docfile" type="file" name="docfile"/> 

Indeed, it is usually best to use a Django form to render the actual field, even if you have gone beyond the whole approach {{form.as_p}} :

 {{form.docfile}} 

PS. if you haven’t read them all, I heartily recommend taking the time to go through all the documentation

+10
source share

Change the sending method to

 <form action="" method="post" enctype="multipart/form-data">{% csrf_token %} 
+2
source share

All Articles