Last active
August 15, 2022 00:14
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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