生成多个 PDF 并压缩它们以供下载,所有这些都在一个视图中 [英] Generate multiple PDFs and zip them for download, all in a single view

查看:23
本文介绍了生成多个 PDF 并压缩它们以供下载,所有这些都在一个视图中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using xhtml2pdf to generate PDFs in my Django View. The idea is to loop over all the instances that are there in the query, then for each instance create a PDF, then add all the generated PDFs to one zip File for download. The xtml2pdf logic is working okay but the looping logic is what gives me headache.

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

So this is my function so far:

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)

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

From that Point I have no idea on what to do next. Any help will be highly appreciated.

推荐答案

试试这个:

Utils.py

def render_to_pdf(template_src, context_dict={}):
    template = get_template(template_src)
    html  = template.render(context_dict)
    buffer = BytesIO()
    p = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), buffer)
    pdf = buffer.getvalue()
    buffer.close()
    if not p.err:
        return pdf#HttpResponse(result.getvalue(), content_type='application/pdf')
    return None


def generate_zip(files):
    mem_zip = BytesIO()

    with zipfile.ZipFile(mem_zip, mode="w",compression=zipfile.ZIP_DEFLATED) as zf:
        for f in files:
            zf.writestr(f[0], f[1])

    return mem_zip.getvalue()

视图.py

def generate_attendance_pdf(modeladmin, request, queryset):

    template_path = 'student/pdf_template.html'

    files = []

    for q in queryset:
        context = {
            'firstname': q.firstname,
            'lastname': q.lastname,
            'p_firstname': q.bceID.firstname
        }
        pdf = render_to_pdf(template_path, context)
        files.append((q.firstname + ".pdf", pdf))

    full_zip_in_memory = generate_zip(files)

    response = HttpResponse(full_zip_in_memory, content_type='application/force-download')
    response['Content-Disposition'] = 'attachment; filename="{}"'.format('attendnace.zip')

    return response

显然,您必须根据需要修改上下文/名称.

Obviously, you have to modify the context/names to what you need.

归功于 -> Neil Grogan https://www.neilgrogan.com/py-bin-zip/

Credit to -> Neil Grogan https://www.neilgrogan.com/py-bin-zip/

这篇关于生成多个 PDF 并压缩它们以供下载,所有这些都在一个视图中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆