如何在Django项目中下载python-docx生成的文档?
How to download a document generated with python-docx in Django project?
我正在尝试了解如何在我的 Django 应用程序中下载使用 python-docx 生成的 Word 文档(我仍在学习,这是我第一次使用文档);在 ajax 的帮助下,我将所有需要的信息发送到视图并调用使用该信息和 returns 文档的函数,然后我尝试发送该文档作为响应以便下载在我提交数据的同一模板中借助 "Download" 按钮(或显示 Web 浏览器下载对话框),但这是我卡住的地方。
将此文档作为响应发送,以便在我提交数据的同一模板中借助 "Download" 按钮(或显示网络浏览器下载对话框)下载它,但在这里是我卡住的地方。
我现在的情况是:
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) 在我的 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) 我创建文档的函数如下所示:
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
如果有任何想法或建议,我将不胜感激,非常感谢。
注意:我已经查看了这些答案(以及其他答案),但运气不佳。
Q1, Q2, Q3,
更新:感谢收到的反馈,我终于找到了如何生成文档并显示下载对话框:
正如所建议的那样,最好的实现方式是使用视图而不是 ajax,因此代码中的最终更新是:
a) 更新视图以按反馈
中所示工作
b) JavaScript - Ajax 对 POST 方法的控制被删除,现在所有的都直接用 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
有了这些更改,当我按下 "Create report"(表单的提交按钮)时,一切都按预期工作(此外,不再需要更多的库)。最后,正如您所建议的那样,这样做比使用 ajax.
更容易
非常感谢大家的帮助。
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
如果您使用常规 link 或表单提交请求,这将有效,但由于您使用的是 $.ajax
,您可能需要在浏览器端做额外的工作才能让客户端下载文件。不使用 $.ajax
.
会更容易
是的,更简洁的选项,如 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
我正在尝试了解如何在我的 Django 应用程序中下载使用 python-docx 生成的 Word 文档(我仍在学习,这是我第一次使用文档);在 ajax 的帮助下,我将所有需要的信息发送到视图并调用使用该信息和 returns 文档的函数,然后我尝试发送该文档作为响应以便下载在我提交数据的同一模板中借助 "Download" 按钮(或显示 Web 浏览器下载对话框),但这是我卡住的地方。
将此文档作为响应发送,以便在我提交数据的同一模板中借助 "Download" 按钮(或显示网络浏览器下载对话框)下载它,但在这里是我卡住的地方。
我现在的情况是:
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) 在我的 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) 我创建文档的函数如下所示:
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
如果有任何想法或建议,我将不胜感激,非常感谢。
注意:我已经查看了这些答案(以及其他答案),但运气不佳。
Q1, Q2, Q3,
更新:感谢收到的反馈,我终于找到了如何生成文档并显示下载对话框:
正如所建议的那样,最好的实现方式是使用视图而不是 ajax,因此代码中的最终更新是:
a) 更新视图以按反馈
中所示工作b) JavaScript - Ajax 对 POST 方法的控制被删除,现在所有的都直接用 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
有了这些更改,当我按下 "Create report"(表单的提交按钮)时,一切都按预期工作(此外,不再需要更多的库)。最后,正如您所建议的那样,这样做比使用 ajax.
更容易非常感谢大家的帮助。
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
如果您使用常规 link 或表单提交请求,这将有效,但由于您使用的是 $.ajax
,您可能需要在浏览器端做额外的工作才能让客户端下载文件。不使用 $.ajax
.
是的,更简洁的选项,如 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