Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save pdf from django-wkhtmltopdf to server (instead of returning as a response)

I'm writing a Django function that takes some user input, and generates a pdf for the user. However, the process for generating the pdf is quite intensive, and I'll get a lot of repeated requests so I'd like to store the generated pdfs on the server and check if they already exist before generating them.

The problem is that django-wkhtmltopdf (which I'm using for generation) is meant to return to the user directly, and I'm not sure how to store it on the file.

I have the following, which works for returning a pdf at /pdf:

urls.py

urlpatterns = [
    url(r'^pdf$', views.createPDF.as_view(template_name='site/pdftemplate.html', filename='my_pdf.pdf'))
]

views.py

class createPDF(PDFTemplateView):
    filename = 'my_pdf.pdf'
    template_name = 'site/pdftemplate.html'

So that works fine to create a pdf. What I'd like is to call that view from another view and save the result. Here's what I've got so far:

#Create pdf
pdf = createPDF.as_view(template_name='site/pdftemplate.html', filename='my_pdf.pdf')
pdf = pdf(request).render()

pdfPath = os.path.join(settings.TEMP_DIR,'temp.pdf')
with open(pdfPath, 'w') as f:
    f.write(pdf.content)

This creates temp.pdf and is about the size I'd expect but the file isn't valid (it renders as a single completely blank page).

Any suggestions?

like image 218
The Bearded Templar Avatar asked Sep 11 '15 05:09

The Bearded Templar


1 Answers

Elaborating on the previous answer given: to generate a pdf file and save to disk do this anywhere in your view:

            ...
            context = {...}  # build your context

            # generate response
            response = PDFTemplateResponse(
                            request=self.request,
                            template=self.template_name,
                            filename='file.pdf',
                            context=context,
                            cmd_options={'load-error-handling': 'ignore'})

            # write the rendered content to a file
            with open("file.pdf", "wb") as f:
                f.write(response.rendered_content)
            ...

I have used this code in a TemplateView class so request and template fields were set like that, you may have to set it to whatever is appropriate in your particular case.

like image 128
mehmet Avatar answered Oct 14 '22 13:10

mehmet