2

I'm having trouble when trying to return a file through a view.

Working case: User submits a form, I instanciate an excel file from these values and return it to the user. After submitting, user got a popup inviting him to download the file. No problem.

Not working case: User selects values from a jstree and submits them with ajax. Again I instanciate an excel file and return it. However, though everything goes fines (no server error, success function triggered in ajax), nothing happens. The file is created this way:

    response = HttpResponse(content_type='application/ms-excel')
    response['Content-Disposition'] = 'attachment; filename="export.xls"'
    response = comparaison(response, wb, ws_same, ws_diff, tree_left, tree_right)
    wb.save(response)
    return response

It goes fine in first case but not in second.

I've also tried to find a workaround by saving the file on the server for a short time and redirect user to its location in this way.

wb.save('export.xls')
return redirect(path_to_export_xls)

It also gives no error but triggers nothing. I've no idea of what I'm missing, the only difference I see is that in the second case, file is not generated from syncronous post submit but I cant why it should be an issue.

Thanks in advance for any suggestion.

PS : here is ajax code.

`$('#button_compare').on('click', function () {
    var raw_left = jstreeDiv.jstree(true).get_checked(true),
        raw_right = jstreeCreate.jstree(true).get_checked(true),
        tree_left = [],
        tree_right = [];
    for(var i = 0; i<raw_left.length ; i++){
        tree_left.push(raw_left[i].li_attr['data-id']);
    }
    for(var i = 0; i<raw_right.length; i++){
        tree_right.push(raw_right[i].li_attr['data-id']);
    }
    $.ajax({
        url: '../Comparer/',
        type: 'POST',
        beforeSend: function (xhr, settings) {
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }
        },
        data: {
            'tree_left': JSON.stringify(tree_left),
            'tree_right': JSON.stringify(tree_right)
        },
        /*
        success:function(response){
            alert('OK');
        },
        error:function (xhr, status, error) {
            return false ;
        }
        */
    });
});

`

May.D
  • 1,832
  • 1
  • 18
  • 34
  • Well, what are you doing in your Ajax to display this file? – Daniel Roseman Aug 01 '17 at 16:10
  • With ajax I just submit data selected by user to the view, which should return a file (with the popup, 'open with or download'). – May.D Aug 02 '17 at 07:03
  • Yes. The Ajax returns a file. What is it doing with it then? – Daniel Roseman Aug 02 '17 at 07:19
  • 1
    Nah ajax is just submitting to the view, its my Python which returns a file. I added my ajax in the question. – May.D Aug 02 '17 at 07:38
  • I know that. I can't seem to make you understand that your Ajax success function needs to *do* something with the response returned from the Python code. – Daniel Roseman Aug 02 '17 at 07:57
  • Allright, Indeed I didnt understand why you insisted so much about Ajax. What I dont understand is : 1) Why using ajax for the submit make it mandatory to return something ? 2) How am I supposed to prompt a file dialog ? In firebug I can see that the server answer contains content_type and content_disposition of my excel file, but nothing pops out. – May.D Aug 02 '17 at 08:13
  • 1
    Because the *whole point* of Ajax is that you take responsibility away from the usual browser workflow. With a normal form, you click the button and the browser sends the data to the server and displays the response. But with Ajax you're taking the responsibility away from the browser and agreeing to handle it in your own code. If you don't want that, don't use Ajax. – Daniel Roseman Aug 02 '17 at 08:16
  • Allright I understand your point, so accord to what I read there is no way to return a file without any complementary plugin. I'll try and find a workaround. Thanks for you explanation. – May.D Aug 02 '17 at 08:23

1 Answers1

0

According to @Daniel Roseman's answer, submitting data through ajax prevent using Django views default return for file. In the end I stored the file in a temp folder on server side and display a popup (with jQueryUI) with a link to the file and delete the file after user download.

May.D
  • 1,832
  • 1
  • 18
  • 34