Home > Back-end >  How to convert html to pdf in django?
How to convert html to pdf in django?

Time:06-14

I'm starting with Django and I working with HTML and I would like to convert to pdf. I have this view wich I get the data registered in my DB by id:

def contrato(request, id):
return render(request,'contrato\contrato.html', {'asociado': get_queryset(id)})

This renders me the following html, it is something simple:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CPS</title>
    
</head>
<body>
    <h1>Contrato de Prestación de Servicios</h1>
    <div>         
        <ul>
            {% for dato in asociado %}
            <li>Función/Título: {{ dato.job_title }}</li>
            <li>nombre completo: {{ dato.first_name }} {{ dato.last_name }}</li>
            <li>Email: {{ dato.email }}</li>
            <li>RFC: {{ dato.rfc }}</li>
            <li>CURP: {{ dato.curp }}</li>
            <li>Clabe: {{ dato.interbank_key }}</li>
            <li>País:  {{ dato.country }}</li>
            <li>Status:  {{ dato.status }}</li>
            <li>Creado: {{dato.created}}</li>
            {% endfor %}
        </ul>
    </div>
</body>
</html>

How can I convert this html to pdf with the registered data to download. I have only achieved an empty pdf (without the data) or only with the H1 header.

I will appreciate any help!

CodePudding user response:

You can use wkhtml2pdf, which will need a HTML document and will generate a pdf file,then return to the generated file to the user, something like this

def contrato(request, id):
   HTML =  render(request,'contrato\contrato.html', {'asociado': get_queryset(id)}).content
   f = open("/tmp/report.html","w")
   f.write(HTML)
   f.close()
   import subprocess
   subprocess.run("wkhtml2pdf /tmp/report.html /tmp/report.pdf")
   return FileStream(open("/tmp/report.pdf","rb"), as_attachment=True)

CodePudding user response:

Doing this without an external library is going to be pretty complicated and involves transpiling the HTML to PDF.

Instead, you'll probably want to use a library like xhtml2pdf.

First pip install xhtml2pdf. Then update your controller function:

  from xhtml2pdf import pisa
  
  # ...
  
  def contrato(request, id):
    if request.path_info.split('.')[-1] == "pdf"
      return render_pdf(request, 'contrato/contrato.html', {'asociado': get_queryset(id)})

    return render(request, 'contrato\contrato.html', {'asociado': get_queryset(id)})

  def render_pdf(request, template_path, context)
    filename = f'{template_path.split('.')[0]}.pdf'
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = f'attachment; filename="{filename}"'

    template = get_template(template_path)
    html = template.render(context)

    pisa_status = pisa.CreatePDF(html, dest=response)

    if pisa_status.err:
      return HttpResponse(f'We had some errors <pre>{html}</pre>')

    return response

For more advanced use cases, you'll probably want to refer to the documentation linked above.

  • Related