I am trying to generate a PDF with data previously entered in Django, the base of the PDF is with HTML, when creating the HTML it is rendered in order and as I want when viewing it with the “”Live Preview” extension in Visual Studio Code, but when transform it to PDF in my project, it is generated badly and messy (I’m sorry if I describe myself badly, it’s the first time I use this platform D:)The idea is that it looks something like this: HTML, but when you download the PDF it looks like this: Bad PDF
As a reference to make the PDF functionality I used this video: https://www.youtube.com/watch?v=J3MuH6xaDjI, this is HTML that I am using to generate the PDF:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cotización - SOLUPLAST</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f4f4f4;
}
.container {
max-width: 800px;
margin: 0 auto;
background-color: #fff;
padding: 20px;
border: 1px solid #ddd;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.header {
display: flex;
justify-content: left;
align-items: flex-start;
}
.logo {
order: -1;
}
.header img {
position: absolute;
max-width: 120px;
}
.header .info {
margin-top: 90px;
text-align: left;
font-size: 0.9em;
color: #000000;
font-weight: bold;
}
.header .quote-info {
text-align: center;
border: 2px solid red;
padding: 10px;
margin-top: 10px;
background-color: #fff8f8;
font-weight: bold;
position: relative;
left: 450px;
color: red;
}
.details, .products-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.details th, .details td, .products-table th, .products-table td {
border: 1px solid #4b4eda;
padding: 10px;
text-align: left;
}
.details th {
background-color: #f9f9f9;
}
.products-table th {
background-color: #f1f1f1;
}
.totals {
float: right;
text-align: right;
margin-top: 20px;
}
.totals table {
border-collapse: collapse;
}
.totals td {
padding: 5px 10px;
}
.conditions {
margin-top: 40px;
font-size: 0.9em;
line-height: 1.5;
}
.conditions p {
margin: 10px 0;
}
.bank-info {
margin-top: 20px;
text-align: center;
}
.bank-info p {
margin: 5px 0;
}
</style>
</head>
<body>
<div class="container">
<!-- Header Section -->
<div class="header">
<div class="logo">
<img src="image.png" alt="Logo de SOLUPLAST">
</div>
<div class="info">
<p>Razón Social: Default name</p>
<p>Web: www.myweb.cl</p>
<p>Teléfono: +56 9 9999 9999</p>
<p>Dirección: Normal #10155</p>
<p>Bodega: 123</p>
</div>
<div class="quote-info">
<p>RUT: 12.345.678-9</p>
<p>COTIZACIÓN</p>
<p>Nº 0598-5958</p>
</div>
</div>
<!-- Client and Seller Details -->
<table class="details">
<tr>
<th>Señor(es)</th>
<td>Default enterpraise</td>
<th>RUT</th>
<td>99.999.999-9</td>
</tr>
<tr>
<th>Atención</th>
<td>SR. Name name</td>
<th>Teléfono</th>
<td>+56 1 2345 6789</td>
</tr>
<tr>
<th>Dirección</th>
<td>Adress #1234</td>
<th>E-mail</th>
<td>[email protected]</td>
</tr>
<tr>
<th>Comuna</th>
<td>Place</td>
<th>Ciudad</th>
<td>City</td>
</tr>
</table>
<table class="details">
<tr>
<th>Vendedor</th>
<th>Teléfono Móvil</th>
<th>Correo</th>
<th>Fecha de Emisión</th>
</tr>
<tr>
<td>Salesman</td>
<td>+56 9 9999 9999</td>
<td>[email protected]</td>
<td>1/1/2001</td>
</tr>
</table>
<!-- Products Table -->
<table class="products-table">
<thead>
<tr>
<th>Código</th>
<th>Descripción</th>
<th>Cantidad</th>
<th>Precio Unitario</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>001</td>
<td>Product description</td>
<td>15,000</td>
<td>$ 15,0</td>
<td>$ 225,000.0</td>
</tr>
<!-- Agregar más filas según sea necesario -->
</tbody>
</table>
<!-- Totals -->
<div class="totals">
<table>
<tr>
<td><strong>NETO</strong></td>
<td>$ 225,000.0</td>
</tr>
<tr>
<td><strong>IVA 19%</strong></td>
<td>$ 42,750.0</td>
</tr>
<tr>
<td><strong>TOTAL</strong></td>
<td>$ 267,750.0</td>
</tr>
</table>
</div>
<!-- Commercial Conditions -->
<div class="conditions">
<p><strong>Condiciones comerciales:</strong></p>
<p>Valores Unitarios no incluyen IVA.</p>
<p>Condiciones de pago: 30 DÍAS FECHA FACTURA.</p>
<p>Plazo Entrega: 24 a 48 HRS. Una vez recibida su orden de compra.</p>
<p>Entrega en su bodega de Santiago o en transporte elegido por el cliente por pagar.</p>
<p>Monto mínimo para despacho: $150,000.0 neto en Santiago.</p>
<p>Productos a pedido consideran tolerancia de fabricación de – 10%.</p>
</div>
<!-- Bank Information -->
<div class="bank-info">
<p>Transferencias a nombre de Nombre Apellido.</p>
<p>Cuenta corriente: 0000000 Bank .</p>
<p>Enviar comprobante al e-mail: [email protected]</p>
</div>
</div>
</body>
</html>
and here is the views in case it is of any use:
def generate_pdf(request, *args, **kwargs):
# Get the value of 'pk' from the keyword arguments passed to the function
pk = kwargs.get('pk')
# Try to get an Ordenes object with the provided 'pk'
order = get_object_or_404(Ordenes, pk=pk)
# Get the order number from the order object
order_number = order.order_number
# Define the path of the HTML template that will be used to generate the PDF
template_path = 'pdf_quote.html'
# Define the context that will be passed to the template. This context contains the order object
context = {'order': order}
# Create an HTTP response object with the content type set to 'application/pdf'
response = HttpResponse(content_type='application/pdf')
# Set the 'Content-Disposition' header of the response to indicate that the response should be treated as a file to download
response['Content-Disposition'] = f'attachment; filename="quote_{order_number}.pdf"'
# Find the template and render it
template = get_template(template_path)
html = template.render(context)
# Create a PDF
pisa_status = pisa.CreatePDF(
html, dest=response)
# If there is an error, show a view with the error
if pisa_status.err:
return HttpResponse('We had some errors <pre>' + html + '</pre>')
# If everything goes well, return the response with the PDF
return response
Thank you for your attention.
bbaez is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.