Eldamir
Eldamir

Reputation: 10062

Python3 Django -> HTML to PDF

There are a lot of different ways of generating pdfs from a django webpage in python2. The most clean, probably, is pisa and reportlab. These do not work for python3 though.

So far, the only method I've had success with is to render the template, write it to a file, and then use wkhtmltopdf via subprocess.popen. This works alright, but it doesn't load any of my static files, such as css and images.

Are there any proper solutions? can wkhtmltopdf read my staticfiles from the command line, in some way, or is there a library like pisa/reportlab, which supports python3?

I haven't been able to finde such a library

Upvotes: 10

Views: 15753

Answers (4)

Savad KP
Savad KP

Reputation: 1654

I have tried pydf in Python3, its working fine.

pip install python-pdf

For python2 use pip install python-pdf==0.30.0

Documentation https://github.com/tutorcruncher/pydf

Upvotes: 0

metakermit
metakermit

Reputation: 22291

I looked into Weasyprint, wkhtmltopdf and even LaTeX, but all have external binary dependencies that are difficult to deploy to services such as Heroku.

The best combination I found so far that works in Django on Python 3 is using Reportlab (now works on Python 3) + xhtml2pdf. xhtml2pdf only recently added beta Python 3 support so you need to install it with:

pip install --pre xhtml2pdf

If you have these two installed, you can either use xhtml2pdf directly or install the django-easy-pdf package which provides a TemplateView to inherit from and an example base template & styling to get you started quickly. Follow their quickstart instructions and you can quickly prepare something like a detail view that renders to PDF like:

class InvoicePDFView(PDFTemplateView):
    template_name = "invoice_pdf.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        myinstance = get_object_or_404(MyModel, pk=context['pk'])
        context['myinstance'] = myinstance
        return context

And in your urls.py you'd add something like:

url(r'invoice/(?P<pk>[^/]+)/$', InvoicePDFView.as_view(), name='invoice')

Upvotes: 6

Dev Rishi Khare
Dev Rishi Khare

Reputation: 506

wkhtmltopdf requires

  • CSS to be inlined
  • static files to be locally present on the server
  • static file urls to be os paths, eg: /home/ubuntu/project/project/static/file_name

Upvotes: 0

Christian Schmitt
Christian Schmitt

Reputation: 892

You could use Weasyprint. You could easily render directly.

You could do something like that:

    html = HTML(string=htmlstring)
    main_doc = html.render()
    pdf = main_doc.write_pdf()
    return HttpResponse(pdf, content_type='application/pdf')

To render your Django view to HTML, you could simply use the shortcut render_to_string(self.template_name, context, context_instance=RequestContext(self.request))

Be aware, when using This with a Synchronous Webserver/WSGI Server ALL requests will be blocked until the PDF is rendered. So consider using an ASYNC Worker.

Upvotes: 13

Related Questions