4

I am using django 1.5, python 2.7 and jquery 1.9. I have a form which has precisely 2 fields i.e. title and document. When I press submit I want the users chosen document to be present in the request.FILES as shown in the view.

When I submit the regular form (without ajax), this works fine, but with ajax I do not get the file field in my request. Any suggestions on how to upload a file using ajax.

HTML:

<form enctype="multipart/form-data" action="{% url 'upload_document' %}" method="post" id="uploadForm">
    {% csrf_token %}
        <ul>
          <li>
            <div>Title</div>
            <input id="title" type="text" maxlength="200"/>
            <div class="error"></div>          
          </li>

          <li>
            <div>Upload File</div>
            <input id="document" type="file" size="15" />
            <div class="error"></div>
          </li>
        </ul>

      <input type="submit" value="submit"/></p>
</form>   

FORMS.PY:

class UploadForm( forms.Form ):
    document = forms.FileField()
    title = forms.CharField(max_length = 200)

    def clean(self):
        cleaned_data = super(UploadForm, self).clean()
        return cleaned_data

    def save(self, *args, **kwargs):
        title = self.cleaned_data['title']
        doc = self.cleaned_data['document']

        document = Document(title = title, document = doc)
        document.save()
        return document

SCRIPT:

<script type="text/javascript">
    $("#uploadForm").submit(function(event){
      event.preventDefault();
      $.ajax({
        url : "{% url 'upload_document' %}",
        type: "POST",
        data : {csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].value,
                title: document.getElementById('title').value,
                //document: document: document.getElementById('document'),
        },
        dataType : "json",
        success: function( response ){
           if(response == "True"){
            // success
           }
           else {
            //append errors
           }
        }
      });
  }); 
</script>

VIEWs.PY

def upload_document(request): 
    print request.POST
    print request.FILES
    if request.is_ajax():
        if request.method == 'POST':
            form = UploadForm(request.POST, request.FILES, user = request.user)

            if form.is_valid():
                form.save()
                return HttpResponse(simplejson.dumps('True'), mimetype = 'application/json' )
            else:
                errors = form.errors
                return HttpResponse(simplejson.dumps(errors), mimetype = 'application/json' )
4
  • 1
    Files cannot be uploaded via AJAX unless you use some jQuery plugins (because uploading of files requires multipart contents to be sent to the server). Commented Apr 6, 2013 at 7:47
  • Ahan, so what next do you suggest? Any plugins you've used for the same purpose? Commented Apr 6, 2013 at 7:49
  • I used some plugins a long back and therefore, I indeed cannot suggest any one of them, sorry and additionally, I don't know much about django and python. Commented Apr 6, 2013 at 7:55
  • Ohhh!! Thanx anyways. Do post if you get anything for this :) Commented Apr 6, 2013 at 8:00

2 Answers 2

3

The answer to that question is not that simple. First of all if you intend to support old browsers then indeed it gets nasty. You have to deal with hidden iframes and some JavaScript tricks. I do advice using some well-known scripts for that like jQuery-File-Upload.

But the world is evolving and new technologies arise including HTML5. There's a new File API which is available in most modern browsers ( IE10+, FireFox3.6+, Chrome13+, see: http://caniuse.com/fileapi ) which can be used for that. First you need some HTML:

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

Then you can bind to (for example) change event:

$('#file-select').change( handleFileSelect );

and finally the handler itself:

var data = {};

function createReaderHandler(name) {
  return function(ev) {
    data[name] = ev.target.result;
  };
}

function handleFileSelect(ev) {
  var files = ev.target.files; // FileList object

  // Loop through the FileList
  for (var i = 0; i < files.length; i++) {
    var file = files[i],
        name = file.name || file.fileName,
        reader = new FileReader();

    reader.onload = createReaderHandler(name);
    reader.readAsText(file);
  }
}

Once the data is loaded into JavaScript memory (note that the operation is asynchronous) you can send it via AJAX like any other data. There are more options: depending on your file you can read it as a binary data using .readAsBinaryString and so on. Google is your friend. :)

Also I think there already are good scripts for uploading files with a fallback to old methods. This one can be interesting (haven't tried it):

http://www.plupload.com/

Sign up to request clarification or add additional context in comments.

1 Comment

Can u explain please I am not able to understand. I am working with django. Can I make a file object push it into JSON and send it to the python script so I can upload it so s3 using my python script? You do not need to worry about the python part thing is I want to get the file to python first.
0

I think the issue is in the submit button, change it into normal button ie, <button type='button' id='submit'>submit</button>(by default all buttons in form are submit) and the ajax as

$('#submit').on('click',function(){
    frm = $(this).parents('form')
    $.ajax({
          type: frm.attr('method'),
          dataType:'json',
          url: frm.attr('action'),
          data: frm.serialize(),
          async: false,
          success: function (data) {
              console.log('success')
          },
          error: function(data) {
              console.log("Something went wrong!");
          }
})

All others will be same Just try it will work

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.