2

After reading other questions on similar subject, I still do not understand what's wrong with this code.

I am testing a code that uses Jquery Form plugin. I added a call in the view to the template, to display it for 1st time so user can select file and upload. But it never sends the AJAX request, hence the code section in view is not executed. Although not shown here, jQuery library and the jQueryForm plugin are indeed being called.

Template:
<form id="uploadForm"  method="post" enctype="multipart/form-data">
                            {% csrf_token %}
        <input id="fileInput" class="input-file" name="upload" type="file">
        {{ form.docfile }}
        <span class="upload-message"></span>
        <input type="submit" value="Upload" />
</form>
<script>
    var message = '';
    var options = {
        type: "POST",
        url: '/upload/file/',
        error: function(response) {
            message = '<span class="error">We\'re sorry, but something went wrong. Retry.</span>';
            $('.upload-message').html(message);
            $('fileInput').val('');
        },
        success: function(response) {
            message = '<span class="' + response.status + '">' + response.result + '</span> ';
            message = ( response.status == 'success' ) ? message + response.fileLink : message;
            $('.upload-message').html(message);
            $('fileInput').val('');
        }
    };
    $('#uploadForm').ajaxSubmit(options);
</script>

View:

def upload(request):
    response_data = {}

    if request.method == 'POST':
        if request.is_ajax:
            form = UploaderForm(request.POST, request.FILES)

            if form.is_valid():
                upload = Upload(
                upload=request.FILES['upload']
            )
            upload.name = request.FILES['upload'].name
            upload.save()

            response_data['status'] = "success"
            response_data['result'] = "Your file has been uploaded:"
            response_data['fileLink'] = "/%s" % upload.upload

            return HttpResponse(json.dumps(response_data), content_type="application/json")

        response_data['status'] = "error"
        response_data['result'] = "We're sorry, but kk something went wrong. Please be sure that your file respects the upload conditions."

        return HttpResponse(json.dumps(response_data), content_type='application/json')
    else:
        form = UploaderForm()
        return render(request, 'upload.html', {'form': form})

It does call template correctly during first time, it displays buttons, it executes the script again but the form is not valid, so response_data is with error.

What am I missing?

Thanks, Ricardo

Rmartin
  • 243
  • 3
  • 6
  • 14

3 Answers3

0

You can try using the example from API section instead, just look at the source code:

$('#uploadForm').ajaxForm({
    beforeSubmit: function(a,f,o) {
        $('.upload-message').html('Submitting...');
    },
    success: function(data) {
        $('.upload-message').html('Done!');
    }
});

and the HTML:

<form id="uploadForm" action="/upload/file/" method="post" enctype="multipart/form-data">
                        {% csrf_token %}
    <input type="hidden" name="MAX_FILE_SIZE" value="100000">
    File: <input type="file" name="file">
    {{ form.docfile }}
    <span class="upload-message"></span>
    <input type="submit" value="Upload" />
</form>
mariodev
  • 13,928
  • 3
  • 49
  • 61
  • I guess I should use the array for file value, right? How could I do it? Also for the form, should I just pass $('#uploadForm')? – Rmartin Dec 23 '13 at 17:04
0

How it is supposed to be worked if there are no form data send in your script.

var options = {
    type: "POST",
    url: '/upload/file/',
    data: new FormData(document.getElementById('uploadForm')),
    processData: false,
    contentType: false,
    error: function(response) {
        message = '<span class="error">We\'re sorry, but something went wrong. Retry.</span>';
        $('.upload-message').html(message);
        $('fileInput').val('');
    },
    success: function(response) {
        message = '<span class="' + response.status + '">' + response.result + '</span> ';
        message = ( response.status == 'success' ) ? message + response.fileLink : message;
        $('.upload-message').html(message);
        $('fileInput').val('');
    }
};
catherine
  • 22,492
  • 12
  • 61
  • 85
  • Thanks Catherine. I thought the line "$('#uploadForm').ajaxSubmit(options);" would do that. Still, adding the 3 lines (with data, processData and contentType), the view does not recognize the request as AJAX and provides the error. – Rmartin Dec 23 '13 at 14:24
0

You have at least one problem with you view - this:

if not request.GET:
    return render(request, 'upload.html') 

will prevent further execution when request.GET is empty which is the case when doing a POST request.

bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
  • Thanks Bruno. I put that if statement since view evaluates the request as not AJAX and jumps to the error message and returns. – Rmartin Dec 23 '13 at 14:29
  • I am confused the HTML file would be called if the original view code does not call it anywhere. I am just testing it out so I can adjust it later to my needs. – Rmartin Dec 23 '13 at 14:42