Создайте несколько PDF-файлов и заархивируйте их для загрузки, все в одном представлении - PullRequest
6 голосов
/ 11 января 2020

Я использую xhtml2pdf для создания PDF-файлов в моем Django Просмотр. Идея состоит в том, чтобы l oop по всем экземплярам, ​​которые есть в запросе, затем для каждого экземпляра создать PDF, а затем добавить все созданные PDF-файлы в один ZIP-файл для загрузки. xtml2pdf logi c работает нормально, но циклическая логика c вызывает у меня головную боль.

Итак, это моя функция:

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)

С этого момента я понятия не имею, что делать дальше. Любая помощь будет высоко оценена.

1 Ответ

0 голосов
/ 11 января 2020

Если вам нужно сгенерировать несколько файлов PDF и отправить их в виде ответа в виде zip-файла, вы можете сохранить отчеты в памяти и установить их как dest при вызове pisa.CreatePDF. Затем получите список отчетов в памяти, zip их и отправьте в виде 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')

This по-прежнему генерирует ошибку [Errno 2] No such file or directory: 'cheque_number.pdf'.

...