Django将Excel保存到桌面

时间:2014-01-16 10:14:05

标签: jquery python django excel

所以,我认为我的问题很简单,但我有一些问题:)

所以在我用Django编写的应用程序中,我使用Ajax调用创建Excel文件:

            $.ajax({
                url: '/ajax-send-xls-desktop/',
                type: 'POST',
                contentType: "application/vnd.ms-excel",
                data: JSON.stringify(data_xls),
                dataType: 'text',
                success: function(result) {
                    window.open('data:application/vnd.ms-excel,' + result);
                }
            });

在我的后端,我创建Excel文件并返回响应,如下所示:

        response = HttpResponse(mimetype="application/vnd.ms-excel")
        response['Content-Disposition'] = 'attachment; filename=opispozycji.xls'
        response['Content-Type'] = 'application/vnd.ms-excel; charset=utf-8'
        book.save(response)

我收到的一切都是很多人物:

    N*8X"��1���Arial1���Arial1���Arial1���Arial1���Arial1���Arial1���Arial1���Arial
�General���� �� ���� �� ���� �� ���� �� ���� �� ���� �� ���� �� ���� �� ���� �� ���� ��
���� �� ���� �� ���� �� ���� �� ���� �� ���� �� �� �� �� �� �� �� ���`��Opis pozycji��
PDane wygnerowane przez Interzam - Internetowa Platforma Zarzdzania Zam�wieniamiSIDCPV

任何人都可以确认问题出在charset编码中吗?

3 个答案:

答案 0 :(得分:0)

这对我有用:

response = HttpResponse(mimetype="application/ms-excel")
response['Content-Disposition'] = "attachment; filename=%s" % "excel.xls"
book.save(response)
return response

我只是链接到查看网址和显示的结果对话框。用ajax调用它不能完成......

<强>更新

我找到了一个解决方案解决方案(使用表单的iframe),以便您需要在此处动态请求文件 - Download a file by jQuery.Ajax。你可以使用@JohnCulviner创建的插件 - http://johnculviner.com/jquery-file-download-plugin-for-ajax-like-feature-rich-file-downloads/或我的小函数ajax_download

// creates iframe and form in it with hidden field,
// then submit form with provided data
// url - form url
// data - data to form field
// input_name - form hidden input name

function ajax_download(url, data, input_name) {
    var $iframe,
        iframe_doc,
        iframe_html;

    if (($iframe = $('#download_iframe')).length === 0) {
        $iframe = $("<iframe id='download_iframe'" +
                    " style='display: none' src='about:blank'></iframe>"
                   ).appendTo("body");
    }

    iframe_doc = $iframe[0].contentWindow || $iframe[0].contentDocument;
    if (iframe_doc.document) {
        iframe_doc = iframe_doc.document;
    }

    iframe_html = "<html><head></head><body><form method='POST' action='" +
                  url +"'>" +
                  "<input type=hidden name='" + input_name + "' value='" +
                  JSON.stringify(data) +"'/></form>" +
                  "</body></html>";

    iframe_doc.open();
    iframe_doc.write(iframe_html);
    $(iframe_doc).find('form').submit();
}

在你的情况下(例如点击事件):

$('#someid').on('click', function() {
    ajax_download('/ajax-send-xls-desktop/', data_xls, 'data');
});

答案 1 :(得分:0)

Data URI scheme提到base 64编码作为选项。另一种方法是进行相关的字符编码。我建议你基于64编码数据。 Here is a question这将帮助你做到这一点。

答案 2 :(得分:0)

你真的需要使用Ajax吗?这似乎是过于复杂的事情。

我在我的应用程序中有excel下载,但它们是标准的Django视图。其中大多数是基于类的通用视图,我已经覆盖了render_to_response方法并使用excel设置内容类型。

所以我有一个标准的ListView我的对象生成HTML,而ExcelListView覆盖了渲染到响应方法,编写excel而不是将其传递给HTML模板。

class ViewToExcel():
    """
    This class will implement the excel writing functionality, by overwriting the render_to_response method
    """
    headings2attrributes = {}  # empty default

    def render_to_response(self, context, **response_kwargs):
        """
        Returns a response with a an excel sheet.
        """
        self.generate_headings()   # specific to my application

        wbk = xlwt.Workbook()
        sheet = wbk.add_sheet('sheet 1')

        # Create the HttpResponse object with the appropriate CSV header.
        response = HttpResponse(mimetype='application/vnd.ms-excel')
        response['Content-Disposition'] = 'attachment; filename=Report.xls'

       row_num = 0
       col_num = 0 

       ## write row of headings
       for hd_att in self.headings2attrributes :
            sheet.write(row_num, col_num , hd_att[0])
            col_num += 1
            row_num += 1

      object_list = self.get_queryset()

    # write rows of data ## again, this is fairly specific to my implementation
    for object  in object_list:   ## go through each object instance in queryset
        self.write_object_row(sheet, row_num, 0 , object)
        row_num += 1
    wbk.save(response)    
    return response



class MyView(ListView):
    """
    This will produce the standard HTML page (which should contain a link to the excel download)
    """
    context_object_name = "my_list"
    template_name = "sequencing/MyView.html"

    def get_queryset(self):
       """
       get your objects and populate a queryset / querydict here
       """
        ...        
        ...
        return MyObjects.all().filter(blah, blah= blah)


class MyExcelView( ViewToExcel , MyView):
    """
    This view will subclass both the ViewToExcel class as well as MyView. 
    When it is called it will reuse the get_queryset method from MyView, but will use RenderToResponse from ViewToExcel - producing excel response, rather than HTML
    The way I have implemented it is that the MyExcelView provides HeadingsToAttributes dictionary, which is used to write the excel. 
    """       
    headings2attrributes_template = [
        ['heading', 'attribbute' ]  , 
        ['heading_2', 'callable' ],