生成多个 PDF 并压缩它们以供下载,所有这些都在一个视图中

Abe*_*edy 7 django zipfile python-3.x xhtml2pdf

我正在使用xhtml2pdf在我的 Django 视图中生成 PDF。这个想法是遍历查询中存在的所有实例,然后为每个实例创建一个 PDF,然后将所有生成的 PDF 添加到一个 zip 文件中以供下载。该xtml2pdf逻辑是工作不错,但在循环逻辑是什么让我头疼。

所以这是我到目前为止的功能:

def bulk_cover_letter(request, ward_id, school_cat_id, cheque_number):
    school_type = SchoolType.objects.get(id=school_cat_id)

    schools_in_school_type = Applicant.objects.filter(
        school_type=school_type, ward_id=ward_id, award_status='awarded'
    ).order_by().values_list('school_name', flat=True).distinct()

    for school in schools_in_school_type:
        beneficiaries = Applicant.objects.filter(school_type=school_type, ward_id=ward_id, award_status='awarded', school_name=school)
        total_amount_to_beneficiaries = Applicant.objects.filter(school_type=school_type, ward_id=ward_id, award_status='awarded', school_name=school).aggregate(total=Sum('school_type__amount_allocated'))
        context = {
            'school_name' : school,
            'beneficiaries' : beneficiaries,
            'total_amount_to_beneficiaries' : total_amount_to_beneficiaries,
            'title' : school + ' Disbursement Details',
            'cheque_number': cheque_number
        }

        response = HttpResponse('<title>Cover Letter</title>', content_type='application/pdf')
        filename = "%s.pdf" %(cheque_number)
        content = "inline; filename=%s" %(filename)
        response['Content-Disposition'] = content
        template = get_template('cover_letter.html')
        html = template.render(context)
        result = io.BytesIO()
        pdf = pisa.CreatePDF(
            html, dest=response, link_callback=link_callback)
        if not pdf.error:
            # At this point I can generate a single PDF.
            # But no idea on what to do next.

    # The zipping logic should follow here after looping all the instances - (schools)
Run Code Online (Sandbox Code Playgroud)

从那时起,我不知道下一步该做什么。任何帮助将不胜感激。

Yan*_*ann 0

如果您需要生成多个 PDF 文件并将它们作为 zip 文件中的响应发送,那么您可以将报告存储在内存中并dest在调用时将其设置为pisa.CreatePDF. 然后在内存中保存一个报告列表,将其压缩,并作为指定另一种内容类型的 Django 响应发送。

例如:

reports = tempfile.TemporaryDirectory()
report_files = {}
for school in schools_in_school_type:
    # ... same code that renerates `html`
    mem_fp = BytesIO()
    pisa.CreatePDF(html, dest=mem_fp)
    report_files[filename] = mem_fp
mem_zip = BytesIO()
with zipfile.ZipFile(mem_zip, mode="w") as zf:
    for filename, content in report_files.items():
            zf.write(filename, content)
response = HttpResponse(mem_zip, content_type='application/force-download')
response['Content-Disposition'] = 'attachment; filename="{}"'.format('cover_letters.zip')
Run Code Online (Sandbox Code Playgroud)

这仍然会产生 的错误[Errno 2] No such file or directory: 'cheque_number.pdf'