简体   繁体   English

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

[英]How to download a document generated with python-docx in Django project?

I'm trying to figure how to download a word document generated with python-docx in my django app (I'm still learning and this is the first time I working with documents);我试图弄清楚如何在我的 django 应用程序中下载使用 python-docx 生成的 word 文档(我还在学习,这是我第一次使用文档); with the help of ajax I send all the information needed to the view and call a function that uses that information and returns the document, then I'm trying to send this document as response in order to download it with the help of a "Download" button (or show web browser download dialog) in the same template from where I'm submitting the data, but here is where I'm stuck.在 ajax 的帮助下,我将所需的所有信息发送到视图并调用使用该信息并返回文档的函数,然后我尝试将此文档作为响应发送,以便在“下载”的帮助下下载它" 按钮(或显示 Web 浏览器下载对话框)在我提交数据的同一模板中,但这是我卡住的地方。

to send this document as response in order to download it with the help of a "Download" button (or show web browser download dialog) in the same template from where I'm submitting the data, but here is where I'm stuck.将此文档作为响应发送,以便在我提交数据的同一模板中的“下载”按钮(或显示 Web 浏览器下载对话框)的帮助下下载它,但这是我卡住的地方。

What I have until now is:到目前为止,我所拥有的是:

1) In javascript I'm sending the information as follows: 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; }

2) In my Django view: 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

3) My function to create the document looks like: 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

I'll be very grateful for any idea or suggestion, many thanks in advance.我将非常感谢任何想法或建议,非常感谢提前。

NOTE: I've reviewed these answers (and others) without luck.注意:我没有运气就查看了这些答案(和其他答案)。

Q1 , Q2 , Q3 , Q4 Q1Q2Q3Q4

UPDATE : Thanks to the feedback received I finally found how to generate the document and show the download dialog:更新:感谢收到的反馈,我终于找到了如何生成文档并显示下载对话框:

As was suggested the best way to achieve its using the view and not ajax, so the final updates in the code are:正如建议的那样,使用视图而不是 ajax 来实现它的最佳方法,所以代码中的最终更新是:

a) Update view to work as show in feedback a) 更新视图以在反馈中显示

b) JavaScript - Ajax control for POST method was removed and now all is handled directly with python (no extra code needed) b) JavaScript - POST 方法的 Ajax 控件已被删除,现在全部由 python 直接处理(不需要额外的代码)

1) View: 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

With those changes now when I press "Create report" (submit button of form) all works as expected (as a plus no more libraries are necessary).现在,当我按下“创建报告”(表单的提交按钮)时,所有这些更改都按预期工作(因为不需要更多的库)。 At the end as you suggested its easier do it in this way than using ajax.最后,正如您所建议的那样,以这种方式比使用 ajax 更容易。

Many thanks to all for your kind help.非常感谢大家的帮助。

Python-docx's Document.save() method accepts a stream instead of a filename. Python-docx 的Document.save()方法接受流而不是文件名。 Thus, you can initialize an io.BytesIO() object to save the document into, then dump that to the user.因此,您可以初始化一个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

This will work if you use a regular link or a form to submit the request, but since you're using $.ajax , you may need to do additional work on the browser end to have the client download the file.如果您使用常规链接或表单提交请求,这将起作用,但由于您使用的是$.ajax ,您可能需要在浏览器端做额外的工作才能让客户端下载文件。 It would be easier not to use $.ajax .不使用$.ajax会更容易。

Yep, a cleaner options, as stated by wardk would be, using https://python-docx.readthedocs.org/ :是的,正如 wardk 所说,更简洁的选择是使用https://python-docx.readthedocs.org/

from docx import Document
from django.http import HttpResponse

def download_docx(request):
    document = Document()
    document.add_heading('Document Title', 0)

    response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document')
    response['Content-Disposition'] = 'attachment; filename=download.docx'
    document.save(response)

    return response

Know more了解更多

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM