Monday, November 12, 2012

How To Render Total Pagenumber In Pdf's With Reportlab

Here is my way to render pdf-files with a "totalPagenumber" option:

Note: The pdf is rendered twice. This may cause problems on low-performance machines or for very big files.

The idea is to pass the number of pages from the first rendering to the second.
To do this I use this function:

from pyPdf import PdfFileReader

def genPdf(renderPageNumber=True):
    filename = pdfWriter()
    if renderPageNumber:
        pdfFile = pdfFileReader(open(filename,'rb'))
        filename = pdfWriter(' / %d'%pdfFile.numPages)

To get the number of pages of a pdf file you need the pyPdf package!

The pdfWriter function generates the pdf file:

from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.rl_config import defaultPageSize
from reportlab.lib.units import inch

def pdfWriter( totalPages='' ):

    filename = 'test.pdf'
    PAGE_HEIGHT=defaultPageSize[1]
    PAGE_WIDTH=defaultPageSize[0]
    styles = getSampleStyleSheet()
    Title = "Hello world"
    pageinfo = "platypus example"

    def myFirstPage(canvas, doc):
        canvas.saveState()
        canvas.setFont('Times-Bold',16)
        canvas.drawCentredString(PAGE_WIDTH/2.0, PAGE_HEIGHT-108, Title)
        canvas.setFont('Times-Roman',9)
        canvas.drawString(inch, 0.75 * inch,"%s: Page %d%s" % (pageinfo, doc.page, totalPages) )
        canvas.restoreState()

    def myLaterPages(canvas, doc):
        canvas.saveState()
        canvas.setFont('Times-Roman', 9)
        canvas.drawString(inch, 0.75 * inch,"%s: Page %d%s" % (pageinfo, doc.page, totalPages) )
        canvas.restoreState()

    doc = SimpleDocTemplate(filename)
    Story = [Spacer(1,2*inch)]
    style = styles["Normal"]
    for i in range(100):
        bogustext = ("Paragraph number %s. " % i) *20
        p = Paragraph(bogustext, style)
        Story.append(p)
        Story.append(Spacer(1,0.2*inch))
    doc.build(Story, onFirstPage=myFirstPage, onLaterPages=myLaterPages)
    return filename

The pdf rendering is done by the ReportLab Toolkit.

To return the pdf as responce in a django app, I use a function like this, where i render the pdf into a cStringIO. The output I add to the response in the view.

Wednesday, November 7, 2012

Django Tips: How To Get Current Variables Or Request

When developing django-apps, I often raise a ZeroDivisionError to stop the script at a certain point.

print 1/0

This makes especially sense to debug code which includes save or redirect commands.

This is also an easy possibility to access the current local vars or request at a certain point of your script via the django traceback.

You have to enable debugging in your django settings:

DEBUG = True