Generate PDF with WeasyPrint having common header/footer and pagination

Tanvir Hossain Bhuiyan picture Tanvir Hossain Bhuiyan · Oct 9, 2016 · Viewed 11.9k times · Source

I am using WeasyPrint to generate PDF in Django. I can generate pdf from a static html file like below -

from django.template import Context, Template
import weasyprint

with open('static_file.html', 'r') as myfile:
    html_str = myfile.read()

template = Template(html_message)
    context = Context({'some_key': 'some_value'})
    rendered_str = template.render(context)

weasyprint.HTML(string=rendered_str).write_pdf('generated.pdf')

But I want to generate a PDF in which, I can include a common header/footer in each page and add pagination.

Also it will be very helpful if anyone can tell how to include a custom font to generate the PDF. I have installed the font in the OS (Ubuntu 14.04) but it is not working.

I have searched a lot on the web about these. But could not find a proper solution.

Answer

Keith picture Keith · Dec 22, 2016

Since Weasyprint supports CSS Paged Media Module Level 3, simple headers and footers (e.g. pagination, like you mentioned) can be accomplished using CSS:

@page {
    @top-right{
        content: "Page " counter(page) " of " counter(pages);
    }
}

Make sure you include your stylesheets when rendering:

HTML(string=rendered_html,
     base_url=settings.SITE_URL).write_pdf(stylesheets=[CSS(settings.STATIC_ROOT + '/css/pdf_render.css')])

However, getting more complex headers/footers to render can be more.. complex. Some people have suggested the method of including a div element in the header that renders only for print (but I must admit I have only been able to get simple elements to render properly with this method):

@page {
    @top-left {
        content: element(pageHeader);
    }
}
@media print {
    #divHeader{
        position: running(pageHeader);
    }
}

There is also another method using fixed positions, as demonstrated in this gist: https://gist.github.com/pikhovkin/5642563