I'm trying to insert a pagebreak after a table in a pdf I'm generating with reportlab, I'm using the following function to generate the pdf:
def render_to_pdf(template_src, context_dict):
template = get_template(template_src)
context = Context(context_dict)
html = template.render(context)
result = StringIO.StringIO()
pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("ISO-8859-1")), dest=result, link_callback=fetch_resources)
if not pdf.err:
return result.getvalue()
return HttpResponse('We had some errors<pre>%s</pre>' % escape(html))
def fetch_resources(uri, rel):
return os.path.join(MEDIA_ROOT, uri.replace(MEDIA_URL, ""))
I'm calling the function from a view this way:
@login_required(login_url=reverse('accounts:login_box'))
def quote_pdf(request, quote_id):
data_pdf = {}
quote = get_object_or_404(Quote, id=quote_id)
data_pdf['pagesize'] = 'letter'
data_pdf['quote'] = quote
pdf = render_to_pdf('rents/quote_pdf.html', data_pdf)
return HttpResponse(pdf, mimetype='application/pdf')
And this is my template (quote_pdf.html)
{% load humanize compress verbatim %}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Cotización No. {{ quote.id }} Flasherz.co/alquiler</title>
<style type="text/css">
@page {
size: {{ pagesize }};
margin: 1cm;
@frame footer {
-pdf-frame-content: footerContent;
bottom: 0cm;
margin-left: 0cm;
margin-right: 0cm;
height: 0cm;
}
}
</style>
<style type="text/css">
body {
font-size: 12px;
line-height: 13px;
}
div#pdf-header {
display: block;
}
div#pdf-header h2 {
display: block;
text-align: center;
font-weight: normal;
line-height: 35px;
font-size: 18px;
}
div#pdf-quote-info {
display: block;
margin-bottom: 20px;
}
p {
margin: 0;
}
table {
border-top: 1px solid #eee;
}
table td, table th {
border-right: 1px solid #eee;
border-bottom: 1px solid #eee;
padding: 5px;
border-left: 1px solid #eee;
}
table .price {
text-align: right;
}
table th {
padding: 5px 0;
font-size: 13px;
text-transform: uppercase;
color: black;
text-align: left;
background-color: #eee;
padding-left: 5px;
}
table p.description {
color: #555;
font-size: 11px;
}
table#quote-info {
border: none;
}
table#quote-info td, table#quote-info th {
border: none;
padding: 0;
}
table td.quantity {
text-align: center;
}
</style>
</head>
<body>
<div id="pdf-header">
<div style="width: 100%; text-align: center;">
<img src="{{ STATIC_URL }}img/quotes-logo.jpeg" alt="Flasherz.co Alquiler" width="600" height="126" />
<div style="display: block; text-align: center; margin: 10px 0;">
<h2>Cotización No. {{ quote.id }}, {{ quote.client_name }}</h2>
</div>
</div>
</div>
<div id="pdf-quote-info">
<table id="quote-info" width="70%" border="none" cellpadding="3" cellspacing="0">
<tr>
<td width="25%">Fecha:</td>
<td width="75%">{{ quote.created|date:'l j' }} de {{ quote.created|date:'F' }} de {{ quote.created|date:'Y' }}</td>
</tr>
{% if quote.client_name %}
<tr>
<td>Cliente:</td>
<td>{{ quote.client_name }}</td>
</tr>
{% endif %}
{% if quote.client_email %}
<tr>
<td>Correo:</td>
<td>{{ quote.client_email }}</td>
</tr>
{% endif %}
{% if quote.client_address %}
<tr>
<td>Dirección:</td>
<td>{{ quote.client_address }}</td>
</tr>
{% endif %}
{% if quote.client_phone %}
<tr>
<td>Teléfono:</td>
<td>{{ quote.client_phone }}</td>
</tr>
{% endif %}
<tr>
<td>Cantidad de días:</td>
<td>{{ quote.rental_days }}</td>
</tr>
</table>
</div>
</div>
<div id="pdf-quote-table">
<table id="quote-table" cellpadding="0" cellspacing="0" width="100%">
{% for category in quote.categories.all %}
<tbody>
<tr>
<th colspan="4" class="category-header">{{ category.category.name }}</th>
</tr>
{% for item in category.items.all %}
<tr>
<td class="quantity" width="10%">
<p>{{ item.quantity }}</p>
</td>
<td class="name" width="50%">
<p class="name">{{ item.name }}</p>
{% if item.content %}<p class="description">{{ item.content }}</p>{% endif %}
</td>
<td class="price" width="20%">
<p>${{ item.price|intcomma }}</p>
</td>
<td class="price total-price" width="20%">
<p>${{ item.total_price|intcomma }}</p>
</td>
</tr>
{% endfor %}
</tbody>
{% endfor %}
<tbody id="others">
<tr>
<th colspan="4" class="category-header">Seguro del 10%</th>
</tr>
<tr>
<td class="quantity"></td>
<td class="name">Seguro 10%</td>
<td class="price"></td>
<td class="price total-price">
<p>${{ quote.get_insurance_price|intcomma }}</p>
</td>
</tr>
</tbody>
{% if quote.discount %}
<tbody id="others">
<tr>
<th colspan="4" class="category-header">Descuento</th>
</tr>
<tr>
<td class="quantity">
</td>
<td class="name">Descuento</td>
<td class="price"></td>
<td class="price total-price">
<p>${{ quote.discount|intcomma }}</p>
</td>
</tr>
</tbody>
{% endif %}
<tbody id="totals">
<tr>
<th colspan="4" class="category-header">Total</th>
</tr>
<tr>
<td class="fake" colspan="2"></td>
<td class="name">Subtotal</td>
<td class="price">
<p>${{ quote.get_subtotal|intcomma }}</p>
</td>
</tr>
<tr>
<td class="fake" colspan="2"></td>
<td class="name">Total días</td>
<td class="price">
<p>${{ quote.get_total_days|intcomma }}</p>
</td>
</tr>
<tr>
<td class="fake" colspan="2"></td>
<td class="name">Total</td>
<td class="price">
<p><strong>${{ quote.get_total|intcomma }}</strong></p>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
I don't know the way to insert a pagebreak after the table to insert the "terms and conditions" in the next page.
Also I have a problem with the images in the pdf, no one is appearing when rendered.
Thanks for helping me
From what I've learned in Pisa's documentation (and this forum post), you can use standard CSS tags like page-break-after
and page-break-before
. Pisa also has some of it's own tags, like pdf:nextpage
. To use this, simply insert the following code block where you would like the page break (the div's are necessary so Pisa's HTML5 parser doesn't try to interpret them):
<div>
<pdf:nextpage />
</div>
I've found the correct method to do it, I needed to insert a few specific styles in the of my pdf
<style type="text/css">
@page {
size: {{ pagesize }};
margin: 1cm;
@frame footer {
-pdf-frame-content: footerContent;
bottom: 0cm;
margin-left: 0cm;
margin-right: 0cm;
height: 0cm;
}
}
.page-break{
page-break-after: always;
}
</style>
Then put a element with .page-break class in where you want to have a page break in your pdf.
I had no luck with the css method.
Just insert this bit of code in your template.html wherever you want a page break. It works for me. I'm not sure, but I think it has to be in a div.
<div>
<pdf:nextpage />
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With