title: Python: ReportLab: How to include page numbers in table of contents?
body: <p>I'm using the Python package ReportLab to create PDF reports.</p>
  
  <p>Using the examples given in the user guide, reportlab website and forums, I've managed to achieve a dynamic table of contents with clickable links but the <strong>page numbers aren't appearing</strong> (in the table of contents).</p>
  
  <p>It would be great if someone could point out what I'm missing from my code below:</p>
  
  <pre><code>from reportlab.platypus import Paragraph, Spacer, Image, PageBreak, KeepTogether
  from reportlab.platypus.doctemplate import BaseDocTemplate, PageTemplate, NextPageTemplate
  from reportlab.platypus.tableofcontents import TableOfContents
  from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
  from reportlab.lib.units import cm, inch
  from reportlab.rl_config import defaultPageSize
  from reportlab.platypus.frames import Frame
  from reportlab.pdfgen.textobject import PDFTextObject
  from reportlab.pdfgen import canvas
  from datetime import datetime
  import os
  styles = getSampleStyleSheet()
  PAGE_HEIGHT=defaultPageSize[1]
  PAGE_WIDTH=defaultPageSize[0]
  
  filename = 'report_template.pdf'
  model_type = 'Cygnus'
  identifier = 'X1'
  date = datetime.now().strftime('%d-%b-%y')
  
  class MyDocTemplate(BaseDocTemplate):
  
      def __init__(self, filename, **kw):
          self.allowSplitting = 0
          BaseDocTemplate.__init__(self, filename, **kw)
          self.pagesize = defaultPageSize
  
      def afterFlowable(self, flowable):
          "Registers TOC entries."
          if flowable.__class__.__name__ == 'Paragraph':
  
              text = flowable.getPlainText()
              style = flowable.style.name
              if style == 'Heading1':
                  level = 0
              elif style == 'Heading2':
                  level = 1
              else:
                  return
              E = [level, text, self.page]
              #if we have a bookmark name, append that to our notify data
              bn = getattr(flowable,'_bookmarkName',None)
              if bn is not None: E.append(bn)
              self.notify('TOCEntry', tuple(E))
  
  
  def report_gen(Test):
  
      def titlePage(canvas, doc):
          canvas.saveState()
          canvas.setFont('Times-Bold', 22)
          canvas.drawCentredString(PAGE_WIDTH/2, PAGE_HEIGHT/2 + 4*12, "Model Test Report")
          canvas.setFont('Times-Bold', 20)
          canvas.drawCentredString(PAGE_WIDTH/2, PAGE_HEIGHT/2 - 6*12, model_type)
          canvas.setFont('Times-Roman', 16)
          canvas.drawCentredString(PAGE_WIDTH/2, PAGE_HEIGHT/2 - 10*12, date)
          canvas.restoreState()
  
      def contentPage(canvas, doc):    
          canvas.saveState()   
          canvas.setFont('Times-Roman', 12)
          canvas.drawString(inch, 0.75*inch, "Page %d | %s %s   %s" %(doc.page, model_type, identifier, date))
          canvas.restoreState()
  
  
      def doHeading(text,sty):
          from hashlib import sha1
          #create bookmarkname
          bn=sha1(text+sty.name).hexdigest()
          #modify paragraph text to include an anchor point with name bn
          h=Paragraph(text+'&lt;a name="%s"/&gt;' % bn,sty)
          #store the bookmark name on the flowable so afterFlowable can see this
          h._bookmarkName=bn
          Story.append(h)
  
      #***Document Structures***#
      doc = MyDocTemplate(filename)
      frameT = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height, id='normal')
      doc.addPageTemplates([PageTemplate(id='TitlePage', frames=frameT, onPage=titlePage), PageTemplate(id='ContentPage', frames=frameT, onPage=contentPage)]) 
      Story = []
      toc = TableOfContents()
      PS = ParagraphStyle
  
      centered = PS(name = 'centered',
          fontSize = 20,
          leading = 16,
          alignment = 1,
          spaceAfter = 20)
  
      h1 = PS(
          name = 'Heading1',
          fontSize = 14,
          leading = 16)
  
  
      h2 = PS(name = 'Heading2',
          fontSize = 12,
          leading = 14)
      #*************************#
  
      #***Title Page***#
      logo = "logo.png"
      im1 = Image(logo, 112.5, 32.5)
      im1.hAlign = 'RIGHT'
      Story.append(im1)
      Story.append(NextPageTemplate('ContentPage'))
      Story.append(PageBreak())
  
      #***Table of Contents***#
      Story.append(Paragraph('&lt;b&gt;Table of Contents&lt;/b&gt;', centered))
      toc.levelStyles = [
                          PS(fontName='Times-Bold', fontSize=14, name='TOCHeading1',
                          leftIndent=20, firstLineIndent=-20, spaceBefore=5, leading=16),
                          PS(fontSize=12, name='TOCHeading2',
                          leftIndent=40, firstLineIndent=-20, spaceBefore=0, leading=12),
                          PS(fontSize=10, name='TOCHeading3',
                          leftIndent=60, firstLineIndent=-20, spaceBefore=0, leading=12),
                          PS(fontSize=10, name='TOCHeading4',
                          leftIndent=100, firstLineIndent=-20, spaceBefore=0, leading=12),
                          ]
      Story.append(toc)
      Story.append(PageBreak())
      #***Content Pages***#
      doHeading('First heading', h1)
      Story.append(Paragraph('Text in first heading', PS('body')))
      Story.append(Spacer(1,12))
      doHeading('First sub heading', h2)
      Story.append(Paragraph('Text in first sub heading', PS('body')))
      Story.append(PageBreak())
      doHeading('Second sub heading', h2)
      Story.append(Paragraph('Text in second sub heading', PS('body')))
      Story.append(PageBreak())
      doHeading('Last heading', h1)
      Story.append(Paragraph('Text in last heading', PS('body')))
  
      doc.multiBuild(Story)
  
  report_gen()
  os.system(filename)
  </code></pre>
  
  <p>Thanks in advance!</p>