如何在Django项目中下载使用python-docx生成的文档?

Leo*_*cia 3 javascript python django httpresponse python-docx

我正在尝试弄清楚如何在我的 django 应用程序中下载使用 python-docx 生成的 Word 文档(我仍在学习,这是我第一次使用文档);在ajax的帮助下,我将所需的所有信息发送到视图并调用使用该信息并返回文档的函数,然后我尝试将此文档作为响应发送,以便在“下载”的帮助下下载它”按钮(或显示网络浏览器下载对话框)在我提交数据的同一模板中,但这就是我陷入困境的地方。

发送此文档作为响应,以便在我提交数据的同一模板中的“下载”按钮(或显示网络浏览器下载对话框)的帮助下下载它,但这就是我陷入困境的地方。

到目前为止我所拥有的是:

1)在javascript中我发送的信息如下:

data = {
        categoria: cat,
        familia: fam,
        Gcas: gcas,
        FI: FI,
        FF: FF,
        Test: test,
        Grafica: grafica
    },
        $.ajax({
            type: 'post',
            headers: {
                "X-CSRFToken": csrftoken
            },
            url: url,
            data: { json_data: JSON.stringify(data) },

            success: function (response) {
                $('#instrucciones').hide(); //Hide a div with a message 
                $('#btndesc').show(); //Show the button to download the file generated                
            }
        });
    return false;
}
Run Code Online (Sandbox Code Playgroud)

2)在我的Django视图中:

def Documento(request):
    if request.method == "GET":
        context={}
        context['form'] = catForm
        return render(request, 'report/report_base.html', context)

    if request.method == 'POST':
    #Data from ajax
    datos = request.POST.get('json_data')
    jsondata = json.loads(datos)
    Gcas = jsondata['Gcas']
    FI = jsondata['FI']
    FF = jsondata['FF']
    grafica = jsondata['Grafica']
    #Using function to create the report
    Reporte = ReporteWord(Gcas, FI, FF, grafica)
    #Response
    response = HttpResponse(content_type='application/vnd.openxmlformats-
    officedocument.wordprocessingml.document')
    response['Content-Disposition'] = 'attachment; filename = "Reporte.docx"'
    response['Content-Encoding'] = 'UTF-8'
    Reporte.save(response)
    return response
Run Code Online (Sandbox Code Playgroud)

3)我创建文档的函数如下所示:

def ReporteWord( gcas, FI, FF, Chart):
    #Cargamos el template
    template = finders.find('otros/Template_reporte.docx')
    document = Document(template) 

    #Header
    logo = finders.find('otros/logo.png')
    header = document.sections[0].header
    paragraph = header.paragraphs[0]
    r = paragraph.add_run()
    r.add_picture(logo)

    #Adding title
    titulo = document.add_heading('', 0)
    titulo.add_run('Mi reporte').bold = True
    titulo.style.font.size=Pt(13)
    .
    Many other steps to add more content    
    .
    .
    #IF I SAVE THE FILE NORMALLY ALL WORKS FINE
    #document.save(r'C:\tests\new_demo.docx')

    return document
Run Code Online (Sandbox Code Playgroud)

我将非常感谢任何想法或建议,非常感谢。

注意:我已经审阅了这些答案(以及其他答案),但没有运气。

Q1Q2Q3Q4

更新:感谢收到的反馈,我终于找到了如何生成文档并显示下载对话框:

正如建议的最好方法是使用视图而不是ajax来实现它,所以代码中的最终更新是:

a)更新视图以如反馈中所示工作

b) JavaScript - POST 方法的 Ajax 控制已被删除,现在所有内容都直接使用 python 处理(不需要额外的代码)

1)查看:

def Reporte(request):
    if request.method == "GET":
        context={}
        context['form'] = catForm
        return render(request, 'reportes/reporte_base.html', context)

    if request.method == 'POST':
        #Getting data needed after submit the form in the page
        GcasID = request.POST.get('GCASS')
        FI = request.POST.get('dp1')
        FF = request.POST.get('dp2')
        Grafica = request.POST.get('options')

        #Function to obtain complete code from GcasID 
        Gcas =  GcasNumber(GcasID)

        #Report creation
        Reporte = ReporteWord(Gcas, FI, FF, Grafica)

        #PART UPDATED TO SHOW DOWNLOAD REPORT DIALOG
        bio = io.BytesIO()
        Reporte.save(bio)  # save to memory stream
        bio.seek(0)  # rewind the stream
        response = HttpResponse(
        bio.getvalue(),  # use the stream's contents
        content_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
    )

        response["Content-Disposition"] = 'attachment; filename = "Reporte.docx"'
        response["Content-Encoding"] = "UTF-8"
        return response
Run Code Online (Sandbox Code Playgroud)

现在,通过这些更改,当我按“创建报告”(表单提交按钮)时,所有这些都按预期工作(另外,不再需要更多库)。最后,正如您所建议的,用这种方式比使用 ajax 更容易做到。

非常感谢大家的热情帮助。

AKX*_*AKX 5

Python-docx 的Document.save()方法接受流而不是文件名。因此,您可以初始化一个io.BytesIO()对象来保存文档,然后将其转储给用户。

Reporte = ReporteWord(Gcas, FI, FF, grafica)
bio = io.BytesIO()
Reporte.save(bio)  # save to memory stream
bio.seek(0)  # rewind the stream
response = HttpResponse(
    bio.getvalue(),  # use the stream's contents
    content_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
)
response["Content-Disposition"] = 'attachment; filename = "Reporte.docx"'
response["Content-Encoding"] = "UTF-8"
return response
Run Code Online (Sandbox Code Playgroud)

如果您使用常规链接或表单提交请求,这将起作用,但由于您使用的是$.ajax,因此您可能需要在浏览器端执行额外的工作才能让客户端下载文件。不使用会更容易$.ajax