Skip to content

Instantly share code, notes, and snippets.

@Pradip-p
Last active August 15, 2022 00:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Pradip-p/5e72a2f030997e4a5b1802b3b1d0e546 to your computer and use it in GitHub Desktop.
Save Pradip-p/5e72a2f030997e4a5b1802b3b1d0e546 to your computer and use it in GitHub Desktop.
weasyprint PDF with footer and header in each page in Django Python
import weasyprint
from django.conf import settings
from django_weasyprint.utils import django_url_fetcher
from django.template.loader import get_template
from django.http.response import HttpResponse
def build_pdf(request,html_content, header_html=None, footer_html=None):
"""
Build a pdf and returns its binary content
For header and footer, CURRENT_PAGE and PAGES_COUNT are replaced by the actual numbers.
"""
def get_page_body(boxes):
for box in boxes:
if box.element_tag == "body":
return box
return get_page_body(box.all_children())
def get_page_and_body(html, css):
if html is None:
return None
html = weasyprint.HTML(
string=html,
base_url=getattr(settings, "WEASYPRINT_BASEURL", None),
url_fetcher=django_url_fetcher,
)
css += "@page { margin 0 !important; }"
document = html.render(stylesheets=[weasyprint.CSS(string=css)])
document_page = document.pages[0]
document_body = get_page_body(document_page._page_box.all_children())
return (
document_page,
document_body.copy_with_children(document_body.all_children()),
)
def preprocess_html(html, context):
for key, value in context.items():
html = html.replace(f"{{{{ {key} }}}}", str(value))
return html
document = weasyprint.HTML(
string=html_content,
base_url=request.build_absolute_uri(),
# base_url=getattr(settings, "WEASYPRINT_BASEURL", None),
url_fetcher=django_url_fetcher,
).render()
if header_html is not None or footer_html is not None:
pages_count = len(document.pages)
for current_page_number, page in enumerate(document.pages, start=1):
context = {"CURRENT_PAGE": current_page_number, "PAGES_COUNT": pages_count}
header_page, header_body = get_page_and_body(
preprocess_html(header_html, context),
css="body {position: fixed; top: -1.5cm;}",
)
footer_page, footer_body = get_page_and_body(
preprocess_html(footer_html, context),
css="body {position: fixed; bottom: -1.5cm;}",
)
page_body = get_page_body(page._page_box.all_children())
if header_body is not None:
page_body.children += header_body.all_children()
if footer_body is not None:
page_body.children += footer_body.all_children()
page.links.extend(header_page.links)
page.links.extend(footer_page.links)
return document.write_pdf()
if __name__ == '__main__':
#load main templates
html_template = get_template('main.html')
rendered_html = html_template.render()
#load header and footer templates
html_header = get_template('header.html')
html_footer = get_template('footer.html')
html_header_rendered = html_header.render()
html_footer_rendered = html_footer.render()
pdf_file = build_pdf(request, rendered_html, header_html=html_header_rendered, footer_html=html_footer_rendered)
http_response = HttpResponse(pdf_file, content_type='application/pdf')
http_response['Content-Disposition'] = 'filename="report.pdf"'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment