DEV Community

Felipe Martins
Felipe Martins

Posted on

"weasyprint" pdf generator using HTML - in django

Why use weasyprint?
Easy to use. Without a doubt, weasyprint is one of the easiest libraries to use when it comes to pdf generators.
Quick request. because of its simplicity, this library tends to convert HTML to pdf very quickly. (it varies depending on the tools you use in HTML, if you need to make many requests through links, there tends to be a longer conversion time)

When not to use weasyprint?
As I had said above, due to the simplicity of the library, newer styling features may not work properly, an example would be flexbox as well as JS cannot be used in this generator either.

Image description

As in the title of this article, I will explain how to make a function to generate a pdf file from HTML, so let's start from the beginning.

First we need to go to the requirements.txt file and add the following code:

weasyprint==53.4
Enter fullscreen mode Exit fullscreen mode

If your project is Dockerized and linux is alpine, I recommend that you have the following lines of code in your Dockerfile:

RUN apk add --no-cache jpeg-dev zlib-dev git gcc musl-dev python3-dev postgresql-dev
RUN apk add py3-pip py3-pillow py3-cffi py3-brotli gcc musl-dev python3-dev pango
RUN apk add py3-pip gcc musl-dev python3-dev pango zlib-dev jpeg-dev openjpeg-dev g++ libffi-dev
RUN apk add --no-cache --virtual .build-deps build-base linux-headers
Enter fullscreen mode Exit fullscreen mode

Now inside the file that we are going to create the function we will have to make the following imports:

# to get the current date and time
import datetime
# library import
from weasyprint import HTML
Enter fullscreen mode Exit fullscreen mode

Now we can create our function containing the logic for our converter. Below is an example of how the function should be constructed:

def export_pdf(request, queryset):
    response = HttpResponse(content_type='aplication/pdf')
    response['Content-Disposition'] = 'attachment; filename=Expense' + \
        str(datetime.datetime.now())+'.pdf'
    response['Content-Transfer-Encoding'] = 'binary'

    query = Query.objects.get(pk=1) #your query with the database object information

    html_string = render_to_string(
        'pdf_template.html',{'templates': query,'total': 0})
    html = HTML(string=html_string) # .html file route

    result = html.write_pdf()

    with tempfile.NamedTemporaryFile(delete=True) as output:
        output.write(result)
        output.flush()

        output = open(output.name, 'rb')
        response.write(output.read())

    return response
Enter fullscreen mode Exit fullscreen mode

With the function ready we can create our HTML file that will be converted. It's up to you where it will be created, the most appropriate thing is to create it inside the template folder inside the app. In the current case, the name of the created file was pdf_template.html.

Image description

To handle the information in your html file, weasyprint accepts resources like jinja to handle your queries.

References:

Top comments (0)