Empty Request.FILES with Django Upload forms
Asked Answered
U

6

66

Trying to use a very simple form to upload a file into a new class instance. I am expecting to have both files in request.FILES but it's empty. I am on the bundled dev server.

Been stuck here and went through all related questions.

wayfinder_map.media_file = request.FILES['media_file'] 

generates

MultiValueDictKeyError: "Key 'media_file' not found in MultiValueDict: {}>"

model

class WayfinderMap(models.Model):
    """ Way-finding Map Config"""


    media_file = models.FileField(upload_to="maps", null=True, blank=True) 
    wall_file = models.FileField(upload_to="maps_data", null=True, blank=True) 

view

@login_required
def create_map(request, form_class=WayfinderMapForm, template_name="wayfinder/map/create.html"):
wayfinder_map_form = form_class(request.user, request.POST or None, request.FILES)

    if wayfinder_map_form.is_valid():
        wayfinder_map = wayfinder_map_form.save(commit=False)
        wayfinder_map.media_file = request.FILES['media_file']
        wayfinder_map.data_file = request.FILES['data_file']
        wayfinder_map.creator = request.user
        wayfinder_map.save()
    return HttpResponseRedirect(wayfinder_map.get_absolute_url())

return render_to_response(template_name, {
    "wayfinder_map_form": wayfinder_map_form,
}, context_instance=RequestContext(request))

template

<form enctype="multipart/form-data" class="uniForm" id="wayfinder_map_form" method="POST" action="">
        <fieldset class="inlineLabels">
            {{ wayfinder_map_form|as_uni_form }}
            <div class="form_block">
                <input type="hidden" name="action" value="create" />
                <input type="submit" value="{% trans 'create' %}"/>
            </div>
        </fieldset>
    </form>
Usurious answered 6/1, 2010 at 3:21 Comment(2)
i think the answers to this similar question will help you out : https://mcmap.net/q/109412/-django-multivaluedictkeyerror-error-how-do-i-deal-with-it/1037459Inequity
Besides enctype="multipart/form" missing, another reason can ben that the file input field doesn't have a name.Anoxia
U
4

It seems as request.FILES is not necessary in this case (good thing cause it's empty ...)

I modified this line

wayfinder_map.media_file = request.FILES['media_file'] 

for

wayfinder_map.media_file = wayfinder_map_form.cleaned_data['media_file'] 

and it works. Not sure what the right way to do thing though... –

Usurious answered 7/1, 2010 at 23:8 Comment(0)
P
241

old question, but somebody might still find this useful.

In order to have your <input type=file> files uploaded and showns in request.FILES, your form MUST contain enctype="multipart/form-data", eg:

<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p }}
<button type="submit">{% trans 'Submit' %}</button>
</form>

otherwise your files will not be uploaded and your request.FILES will be empty.

BTW That's a common solution to a common error. Nevertheless, I still found myself in a situation with an empty FILES (and the file in the POST) when everything else was looking OK. I have the feeling it was a size limit but did not want to spend more time debugging, and just used request.raw_post_data. If ever somebody falls on this issue please add a comment (including precise django version!) and I'll try to debug more deeply.

Paugh answered 6/4, 2011 at 13:23 Comment(6)
@Stefano: I've fallen on this issue too. (Working with django 1.6, python 3.3) I've set encryption type and other thing, but still my request.FILES is empty.Earphone
@alireza, even thou SO is not a "support" site you might try and paste the specifics of your configuration, or a link to code if OS, otherwise it's too difficult to guess what your problem is...Paugh
when you are so much blinded by the framework, simple things like this one is always forgotten. Thank you!Difficult
jQuery Mobile also requires: data-ajax="false"Selfdriven
Note that request.raw_post_data is now request.body as of 1.6Massicot
@T.Christiansen , that saved my life, i've been looking for a solution for more that two daysLanettelaney
C
5

The problem for me was that I am missing the "name" attribute for the file input.

Chopine answered 13/2, 2021 at 3:38 Comment(1)
yes, indeed, i use my custom form, not django forms, and name attribute is required. But how i could know it?)Pox
U
4

It seems as request.FILES is not necessary in this case (good thing cause it's empty ...)

I modified this line

wayfinder_map.media_file = request.FILES['media_file'] 

for

wayfinder_map.media_file = wayfinder_map_form.cleaned_data['media_file'] 

and it works. Not sure what the right way to do thing though... –

Usurious answered 7/1, 2010 at 23:8 Comment(0)
O
3

I know this is an old question, but it is the first result on google for "django request.file empty" so I would like to add a potential solution after searching for two days:

If you submit your files through ajax, make sure to send your form via formData() instead of form.serialize()

see also here: Django JQuery Ajax File Upload

Ominous answered 15/5, 2020 at 12:4 Comment(0)
H
1

I found that If you put put the form in a content block then it seems to work

    {% block content %}
<form enctype="multipart/form-data" class="uniForm" id="wayfinder_map_form" method="POST" action="">
        <fieldset class="inlineLabels">
            {{ wayfinder_map_form|as_uni_form }}
            <div class="form_block">
                <input type="hidden" name="action" value="create" />
                <input type="submit" value="{% trans 'create' %}"/>
            </div>
        </fieldset>
    </form>
{% endblock %}
Heisenberg answered 11/11, 2018 at 11:30 Comment(0)
H
0

I think your troubles may lie in assigning data to a form without first verifying the the request is POST

@login_required
def create_map(request, form_class=WayfinderMapForm, template_name="wayfinder/map create.html"):
  if request.method=='POST':
    wayfinder_map_form = form_class(request.user, data=request.POST, files=request.FILES)

    if wayfinder_map_form.is_valid():
      #save your data
      return HttpResponseRedirect(wayfinder_map.get_absolute_url())

  else:
    wayfinder_map_form=form_class(request.user)

 return render_to_response(template_name, {"wayfinder_map_form": wayfinder_map_form,}, context_instance=RequestContext(request))
Hangbird answered 6/1, 2010 at 5:28 Comment(3)
been using it this way with no problem so far. might be a good check (if necessary) but it certainly does not solve the problem as request.FILES is still emptyUsurious
What do you mean 'no problems so far'? Did this work properly before? Can you post your form class?Hangbird
What I mean is that I've been using forms with no problem, as long as I don't have to use request.FILES, without checking if the method is POST. Does tying request.POST to data in the instantiation of the class like you do could help ? I'll try that and post my form.Usurious

© 2022 - 2024 — McMap. All rights reserved.