hi! /ᐠ. ̫ .ᐟ\ฅ
I’m currently trying to generate pdfs in my django app. For this I’ve settled on using gotenberg
with gotenberg-client
.
I’ve tested generating pdfs outside django with a simple script and it works well.
The problem I’m having is that I’m not too sure what to do on the django side. I want a view that returns a PDF, but when I tried following this example on the documentation the result is a blank pdf.
gotenberg-client
has a method to write the response to a file, which was generated correctly, so I am 99% sure it is something I’m doing wrong on the django side.
Here is the code I’m using to generate pdfs:
def render_pdf_from_template(
template: str,
context: dict[str, object] | None = None,
request: HttpRequest | None = None,
using: str | None = None,
resources: list[Path] | None = None,
) -> bytes | bytearray:
"""Given a django template returns a pdf made with gotenberg
Args:
template (list[str] | str): string or strings to a django template
context (dict[str, object] | None, optional): context that goes inside the template. Defaults to None.
request (HttpRequest | None, optional): optional request for the template. Defaults to None.
using (str | None, optional): template engine to use. Defaults to None.
resources (list[Path] | None, optional): additional paths to resources to render the pdf (images, stylesheets, etc). Defaults to None.
Raises:
ValueError: Raised the if the URL is not found
Exception: Raised if it's not possible to connect to the URL
Returns:
bytes | bytearray: rendered pdf from gotenberg
"""
rendered_html = render_to_string(
template_name=template, context=context, request=request, using=using
)
url = getattr(settings, "GOTENBERG_URL", None)
if not url:
raise ValueError("GOTENBERG_URL missing in settings")
try:
with GotenbergClient(url) as client:
with client.chromium.html_to_pdf() as route:
response = route.string_index(rendered_html)
if resources:
response = response.resources(resources)
response = response.run()
# see if pdf is generated correctly
response.to_file(Path("my-index.pdf"))
return response.content
except ConnectError:
raise Exception(f"Error connecting to {url}")
And here is the mixin I’m adding to my views:
class PDFMixin(TemplateResponseMixin):
resources: list[Path] | None = None
filename: str
content_type = "application/pdf"
def render_to_response(self, context, **response_kwargs):
response_kwargs.setdefault("content_type", self.content_type)
pdf = render_pdf_from_template(
template=self.get_template_names(),
context=context,
request=self.request,
using=self.template_engine,
resources=self.resources,
)
return FileResponse(
pdf, as_attachment=True, filename=self.filename, **response_kwargs
)