views:

318

answers:

1

Initial story

I'm trying to implement file upload using a simple form (I'm pasting stripped version, but all important parts are included):

  <form method="POST" action="" enctype="multipart/form-data">
      <input type="file" name="up_file" size="50">
      <input type="hidden" name="cpk" value="{{c.pk}}">
      <input type="submit" name="btn_submit">
  </form>

Now, server-side script running under wsgi was receiving strange values for "cpk" field and request.FILES was empty empty request.FILES and request.POST dictionaries, so I decided to switch to development server for debugging.

Surprisingly, ipdb debugger hangs after typing both request.POST and request.FILES and pressing enter... On the other hand, when I remove enctype="multipart/form-data" from tag, I'm able to check both request.POST and request.FILES, but of course request.FILES is empty then.

(Also wsgi version seems to be healed by removal of enctype="multipart/form-data"...)

Update

I tried all combinations of Opera 10//Firefox 3.5, enctype="multipart/form-data"//no multipart/form-data and dev server//mod_wsgi. The result is that it's enctype="multipart/form-data" that breaks the show. So now I'm going to check Django bugtracker if it's a known issue.

Meantime, maybe someone here can point me in the right direction

+4  A: 

You may need to provide your view and form code as we use form uploads with enctype="multipart/form-data" in Django 1.1.1 with great success.

The following dummy app, for example, works perfectly in the dev server.

views.py

from django import forms
from django.shortcuts import render_to_response

class UploadForm(forms.Form):
    cpk = forms.CharField(max_length=256)
    f = forms.FileField()

def my_upload_view(request):
    if request.method == 'POST':
        form = UploadForm(request.POST, request.FILES)
        if form.is_valid():
            print "Got cpk",form.cleaned_data['cpk']
            print "Got file",request.FILES['f'].read()
    else:
        form = UploadForm()
    return render_to_response('upload.html', {'form':form})

upload.html

<html>
<body>
    <form enctype="multipart/form-data" method="post">
        {{ form.f }}
        {{ form.cpk }}
        <input type="submit" />
    </form>
</body>
</html>

I'm using the django form instance to render the file input, but it renders the very common <input type="file" name="f" id="id_f" />.

Using this sample, I get the content of the file (I've tested using a simple text file) printed to the terminal from my dev server. The few gotchas and tests I can recommend are:

  • ensure that the file you are uploading is less than settings.FILE_UPLOAD_MAX_MEMORY_SIZE (the default is 2.5 MB)
  • double-check that you haven't defined any custom file upload handlers that may be breaking the upload process (settings.FILE_UPLOAD_HANDLERS)
  • try uploading a very simple file (like a small text file) to see if the issue still persists with something basic
  • use a tool to inspect the raw HTTP request/response traffic (firebug will do this for you, and there are some stand-alone apps that will act as a proxy to help you here too)... sometimes the solution will jump out when you can see the raw traffic.

In case you haven't found them yet, the django file upload docs have a fair number of examples.

Jarret Hardie
I've just tried you dummy app - it stucks if pasted into my project, but works perfectly if run as standalone project! That explains all those anomalies, I haven't even suspected that I might be breaking Django request processing at some point. Thank you!
Tomasz Zielinski