--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/svv/pdf.py Mon Dec 20 23:15:08 2010 +0200
@@ -0,0 +1,435 @@
+# coding: utf-8
+
+"""
+ PDF output
+"""
+
+from reportlab import platypus as rlpp
+from reportlab.lib.units import inch
+from reportlab.lib import pagesizes, styles
+
+from cStringIO import StringIO
+import itertools
+import logging
+import datetime
+
+
+log = logging.getLogger('svv.pdf')
+
+class Styles (object) :
+ """
+ Simple stylesheet
+ """
+
+ samplestyles = styles.getSampleStyleSheet()
+
+ # normal text
+ h1 = styles.ParagraphStyle('Heading1', samplestyles['h1'],
+ fontName = 'Times-Bold',
+ fontSize = 22,
+ spaceBefore = 0,
+ spaceAfter = 0,
+
+ )
+
+ h2 = styles.ParagraphStyle('Heading2', samplestyles['h2'],
+ fontName = 'Times-Bold',
+ fontSize = 14,
+ spaceBefore = 6,
+ spaceAfter = 0,
+ )
+
+ h3 = styles.ParagraphStyle('Heading3', samplestyles['h3'],
+ fontName = 'Times-Italic',
+ fontSize = 12,
+ spaceBefore = 0,
+ spaceAfter = 0,
+ )
+
+ text = styles.ParagraphStyle('Text', samplestyles['Normal'],
+
+ )
+
+ # list indent level
+ list_indent = inch / 4
+
+ # root title
+ list_h1 = styles.ParagraphStyle('ListHeading1', samplestyles['h1'],
+ bulletIndent = 0,
+ leftIndent = 0,
+ )
+
+ # section
+ list_h2 = styles.ParagraphStyle('ListHeading2', samplestyles['h2'],
+ bulletIndent = 0,
+ leftIndent = list_indent,
+ fontName = 'Times-Bold',
+ fontSize = 10,
+ leading = 12,
+ spaceBefore = 6,
+ spaceAfter = 0,
+ )
+
+ # segment
+ list_h3 = styles.ParagraphStyle('ListHeading3', samplestyles['h3'],
+ bulletIndent = 0,
+ leftIndent = list_indent,
+ fontName = 'Times-Italic',
+ fontSize = 10,
+ leading = 12,
+ spaceBefore = 0,
+ spaceAfter = 0,
+ )
+
+ # infot
+ list_text = styles.ParagraphStyle('ListText', samplestyles['Normal'],
+ bulletIndent = 0,
+ leftIndent = list_indent,
+ )
+
+class ListItem (object) :
+ """
+ Indented/nested list
+ """
+
+ @classmethod
+ def seq (cls) :
+ """
+ List numbering.
+
+ Fixed as numeric only for now
+ """
+
+ for idx in itertools.count(1) :
+ yield "%d." % (idx, )
+
+
+ def __init__ (self, title, title_style, text, subseq=None, sublist=None,
+ text_style=Styles.list_text, indent=Styles.list_indent) :
+ """
+ title - title to display as first line
+ title_style - paragraph style for title line
+ text - multi-line texto to display on first or previous lines
+ subseq - sequence of bullet-texts to use for items in sublist
+ sublist - sequence of sub-nodes
+
+ text_style - paragraph style for text lines
+ indent - indentation for text and sub-lists
+ """
+
+ self.title = title
+ self.title_style = title_style
+ self.text = text
+
+ self.subseq = subseq
+ self.sublist = sublist
+
+ self.text_style = text_style
+ self.indent = indent
+
+ def render_pdf (self, bullet=None) :
+ """
+ Yield a series of PDF flowables for this list node and sub-nodes, useable for pdf.DocTemplateBase.build()
+
+ bullet - bullet text to use for this item's paragraph
+ """
+
+ # first line, with possible bullet
+ if self.title :
+ yield rlpp.Paragraph(self.title, self.title_style, bullet)
+
+ elif self.text :
+ yield rlpp.Paragraph(self.text, self.text_style, bullet)
+
+ # indented text after title
+ if self.title and self.text :
+ yield rlpp.Paragraph(self.text, self.text_style)
+
+ if self.sublist :
+ # following lines, indented
+ yield rlpp.Indenter(self.indent)
+
+ # sub-items
+ for item in self.sublist :
+ # get (optional) bullet for item
+ bullet = next(self.subseq, None) if self.subseq else None
+
+ # render item as series of elements
+ for element in item.render_pdf(bullet) :
+ yield element
+
+ # de-dent
+ yield rlpp.Indenter(-self.indent)
+
+
+
+class SignatureBlock (rlpp.Flowable) :
+ """
+ A signature block, with multiple sets of multiple pre-fillied fields.
+ """
+
+ # vertical space per field
+ FIELD_HEIGHT = 2 * inch / 4
+
+ # horizontal offset from top of field to field line
+ FIELD_OFFSET = FIELD_HEIGHT / 2
+
+ # maximum width to scale columns to
+ COL_WIDTH_MAX = 4 * inch
+
+ # empty space to leave below the fields
+ PADDING_BOTTOM = inch / 2
+
+ def __init__ (self, cols, fields, values) :
+ """
+ cols - Column titles
+ fields - Fields titles, describing the horizontal fields
+ values - Pre-filled values as a {(col, field): value} dict
+
+ desc/value strings can contain formatting codes:
+
+ column - title of the current column
+ today - today's date in %d/%m/%Y format
+ """
+
+ self.cols = cols
+ self.fields = fields
+ self.values = values
+
+ def wrap (self, width, height) :
+ """
+ Calculate how much space we use up, returning (width, height)
+ """
+
+ self.width = width
+
+ # consume all available height, to place us at the bottom
+ self.height = max(len(self.fields) * self.FIELD_HEIGHT, height)
+
+ return self.width, self.height
+
+ def formatString (self, text, col_title) :
+ """
+ Format display string using context parameters
+ """
+
+ return text % dict(
+ column = col_title,
+ today = datetime.date.today().strftime("%d/%m/%Y"),
+ )
+
+ # text above field line
+ VALUE_FONT = "Courier-Bold"
+ VALUE_FONT_SIZE = 14
+ VALUE_OFFSET = inch / 12
+
+ # text below field line
+ TITLE_FONT = "Times-Italic"
+ TITLE_FONT_SIZE = 10
+ TITLE_OFFSET = inch / 8
+
+ def draw (self) :
+ """
+ Render full block onto our canvas
+ """
+
+ # target canvas
+ canvas = self.canv
+
+ col_width = min(self.width / len(self.cols), self.COL_WIDTH_MAX)
+ col_margin = col_width * 0.1
+ col_height = len(self.fields) * self.FIELD_HEIGHT + self.PADDING_BOTTOM
+
+ for field_idx, (field_title) in enumerate(self.fields) :
+ h = self.FIELD_HEIGHT
+ y = col_height - h * (field_idx + 1)
+
+ for col_idx, (col_title) in enumerate(self.cols) :
+ w = col_width
+ x = w * col_idx
+ value = self.values.get((col_title, field_title))
+ title = field_title
+
+ value = self.formatString(value, col_title) if value else None
+ title = self.formatString(title, col_title) if title else None
+
+ if value :
+ canvas.setFont(self.VALUE_FONT, self.VALUE_FONT_SIZE)
+ canvas.drawString(x + col_margin + self.VALUE_OFFSET, y - self.FIELD_OFFSET + 2, value)
+
+ # field line
+ canvas.line(x + col_margin, y - self.FIELD_OFFSET, x + w - col_margin, y - h / 2)
+
+ # desc text
+ canvas.setFont(self.TITLE_FONT, self.TITLE_FONT_SIZE)
+ canvas.drawString(x + col_margin + self.TITLE_OFFSET, y - self.FIELD_OFFSET - self.TITLE_FONT_SIZE, title)
+
+class PageTemplate (rlpp.PageTemplate) :
+ """
+ A single-frame page with header and footer.
+ """
+
+ # vertical space available for footer/header, fixed because we can't really flow text vertically
+ HEADER_HEIGHT = 1 * inch
+ FOOTER_HEIGHT = 1 * inch
+
+ COL_FONT_SIZE = 8
+ COL_TITLE_FONT_NAME, COL_TITLE_FONT_SIZE = COL_TITLE_FONT = ("Times-Bold", COL_FONT_SIZE)
+ COL_TEXT_FONT_NAME, COL_TEXT_FONT_SIZE = COL_TEXT_FONT = ("Times-Roman", COL_FONT_SIZE)
+
+
+ def __init__ (self, id='page', page_size=pagesizes.A4, margin=inch, header_columns=None, footer_columns=None) :
+ """
+ id - identifier for this page template
+ page_size - the (width, height) of this page
+ margin - the base margin to use between elements
+
+ header_columns - (title, text) list of header columns
+ footer_columnss - (title, text) list of footer columns
+ """
+
+ self.page_width, self.page_height = self.page_size = page_size
+ self.margin = margin
+
+ self.header_height = self.HEADER_HEIGHT
+ self.footer_height = self.FOOTER_HEIGHT
+
+ # calculate frame
+ self.frame_left = self.margin
+ self.frame_bottom = self.footer_height + self.margin / 2
+ self.frame_top = self.page_height - self.header_height - self.margin / 2
+ self.frame_right = self.page_width - self.margin
+
+ self.frame = rlpp.Frame(self.frame_left, self.frame_bottom, self.frame_right - self.frame_left, self.frame_top - self.frame_bottom)
+
+ # init base template
+ rlpp.PageTemplate.__init__(self, id, frames=[self.frame])
+
+ self.header_columns = header_columns
+ self.footer_columns = footer_columns
+
+
+ def fmt_string (self, text) :
+ """
+ Prepare a string for display by handling format codes
+ """
+
+ # XXX: unicode?
+ return str(text % dict(
+ today = datetime.date.today().strftime("%d / %m / %Y"),
+ ))
+
+
+ def draw_column (self, canvas, x, y, width, title, lines, gray=None) :
+ """
+ Draw a column in the specified position, with the specified lines of text
+ """
+
+ text = canvas.beginText(x, y)
+
+ # grayscale text?
+ if gray :
+ text.setFillGray(gray)
+
+ # title
+ text.setFont(*self.COL_TITLE_FONT)
+ text.textLine(self.fmt_string(title))
+
+ # lines
+ text.setFont(*self.COL_TEXT_FONT)
+ text.textLines(self.fmt_string(lines))
+
+ # draw out
+ canvas.drawText(text)
+
+
+ def draw_columns (self, canvas, x, y, width, columns, **opts) :
+ """
+ Draw a series of columns in the specified position
+ """
+
+ col_count = len(columns)
+ col_width = width / col_count
+
+ x_base = x
+
+ for col_idx, (col_data) in enumerate(columns) :
+ x = x_base + (col_idx * col_width)
+
+ # draw column data at correct offset inside our space
+ self.draw_column(canvas, x, y - self.COL_FONT_SIZE, col_width, *col_data, **opts)
+
+
+ def draw_header (self, canvas) :
+ """
+ Draw page header
+ """
+
+ # offsets
+ x = self.margin
+ h = self.footer_height - self.margin / 4
+ w = self.page_width - self.margin * 2
+
+ # spacer
+ y = self.page_height - self.footer_height
+
+ canvas.setLineWidth(0.5)
+ canvas.line(x - self.margin / 2, y, self.page_width - self.margin / 2, y)
+
+ # columns
+ y = self.page_height - self.margin / 4
+
+ self.draw_columns(canvas, x, y, w, self.header_columns)
+
+
+ def draw_footer (self, canvas) :
+ """
+ Draw page footer
+ """
+
+ # offsets
+ x = self.margin
+ y = self.footer_height
+ w = self.page_width - self.margin * 2
+
+ # spacer
+ canvas.setLineWidth(0.5)
+ canvas.line(x - self.margin / 2, y, self.page_width - self.margin / 2, y)
+
+ # columns
+ self.draw_columns(canvas, x, y - inch / 8, w, self.footer_columns, gray=0.4)
+
+
+ def beforeDrawPage (self, canvas, document) :
+ """
+ Draw page headers/footers
+ """
+
+ self.draw_header(canvas)
+ self.draw_footer(canvas)
+
+class DocumentTemplate (rlpp.BaseDocTemplate) :
+ def __init__ (self, page_templates, title, author, page_size=pagesizes.A4) :
+ """
+ Initialize with fixed list of needed PageTemplates.
+ """
+
+ # we supply the file later
+ rlpp.BaseDocTemplate.__init__(self, filename=None,
+ pageTemplates=page_templates, title=title, author=author,
+ pageSize=page_size
+ )
+
+ def render_string (self, elements) :
+ """
+ Build the document using the given list of Flowables, returning the PDF as a single str.
+ """
+
+ buf = StringIO()
+
+ # build
+ self.build(elements, buf)
+
+ # binary data out
+ return buf.getvalue()
+
--- a/svv/wsgi.py Mon Dec 20 20:51:45 2010 +0200
+++ b/svv/wsgi.py Mon Dec 20 23:15:08 2010 +0200
@@ -4,6 +4,8 @@
WSGI frontend/entry point
"""
+from svv import pdf
+
import werkzeug
from werkzeug import exceptions
from werkzeug import Request, Response
@@ -106,304 +108,62 @@
"""
def respond (self, url_values) :
- from reportlab import platypus as rlpp
- from reportlab.lib.units import inch
- from reportlab.lib import pagesizes, styles
-
- from cStringIO import StringIO
- import itertools
-
- buf = StringIO()
-
- # dimensions
- page_width, page_height = page_size = pagesizes.A4
- header_height = 1 * inch
- footer_height = 1 * inch
-
- margin = inch
- frame_width = page_width - 2 * margin
- frame_height = page_height - footer_height - margin / 2 - margin / 2 - header_height
- frame_bottom = footer_height + margin / 2
- frame_left = margin
- frame = rlpp.Frame(frame_left, frame_bottom, frame_width, frame_height)
title = url_values.get('name', "Hello World")
- def draw_page_tpl (canvas, document) :
- cols = 4
- col_width = (page_width - 2 * margin) / 4
-
- def draw_column (x, y, title, lines, gray=None) :
- text = canvas.beginText(x, y)
-
- if gray:
- text.setFillGray(gray)
-
- # title + rest
- text.setFont("Times-Bold", 8)
- text.textLine(title)
- text.setFont("Times-Roman", 8)
- text.textLines(lines)
-
- canvas.drawText(text)
-
-
- #
- # header
- #
- x = margin
- y = page_height - margin / 4
-
- # spacer
- y = page_height - footer_height
-
- canvas.setLineWidth(0.5)
- canvas.line(x - margin / 2, y, page_width - margin / 2, y)
-
- # columns
- x = margin + 3 * col_width
- y = page_height - margin / 4
-
- today = datetime.date.today()
-
- draw_column(x, y - inch / 6, "Vuokrasopimus", str("%(title)s\n%(today)s" % dict(
- today = today.strftime("%d / %m / %Y"),
- title = title
- ))),
-
-
- #
- # footer
- #
- x = margin
- y = footer_height
-
- # spacer
- canvas.setLineWidth(0.5)
- canvas.line(x - margin / 2, y, page_width - margin / 2, y)
-
- # column
- draw_column(x, y - inch / 6, "Teekkarispeksi Ry", "www.teekkarispeksi.fi", 0.4)
- x += col_width
-
- draw_column(x, y - inch / 6, "Tekniikkavastaava", "Juha Kallas\n045 xxx yyzz\njskallas@cc.hut.fi", 0.4)
- x += col_width
-
- draw_column(x, y - inch / 6, "Varastovastaava", "Joel Pirttimaa\n045 xxx yyzz\njhpirtti@cc.hut.fi", 0.4)
- x += col_width
-
- tpl = rlpp.PageTemplate('page', [frame], onPage=draw_page_tpl, pagesize=page_size)
- doc = rlpp.BaseDocTemplate(buf, pageTemplates=[tpl], title=title, author="Test Author", showBoundary=False, pageSize=page_size)
-
- samplestyles = styles.getSampleStyleSheet()
-
- # normal text
- h1 = styles.ParagraphStyle('Heading1', samplestyles['h1'],
- fontName = 'Times-Bold',
- fontSize = 22,
- spaceBefore = 0,
- spaceAfter = 0,
-
+ tpl = pdf.PageTemplate('id',
+ header_columns = (
+ ("", ""),
+ ("", ""),
+ ("", ""),
+ ("Vuokrasopimus", "%(today)s\n" + title + "\n"),
+ ),
+ footer_columns = (
+ ("Teekkarispeksi Ry", "www.teekkarispeksi.fi"),
+ ("Tekniikkavastaava", "Juha Kallas\n045 xxx yyzz\njskallas@cc.hut.fi"),
+ ("Varastovastaava", "Joel Pirttimaa\n045 xxx yyzz\njhpirtti@cc.hut.fi"),
+ ("", ""),
+ ),
)
- h2 = styles.ParagraphStyle('Heading2', samplestyles['h2'],
- fontName = 'Times-Bold',
- fontSize = 14,
- spaceBefore = 6,
- spaceAfter = 0,
- )
-
- h3 = styles.ParagraphStyle('Heading3', samplestyles['h3'],
- fontName = 'Times-Italic',
- fontSize = 12,
- spaceBefore = 0,
- spaceAfter = 0,
- )
-
- text = styles.ParagraphStyle('Text', samplestyles['Normal'],
-
- )
-
- # standard indent
- list_indent = inch / 4
-
- # root title
- list_h1 = styles.ParagraphStyle('ListHeading1', samplestyles['h1'],
- bulletIndent = 0,
- leftIndent = 0,
+ doc = pdf.DocumentTemplate([tpl],
+ title = title, author = "A. N. Onous"
)
- # section
- list_h2 = styles.ParagraphStyle('ListHeading2', samplestyles['h2'],
- bulletIndent = 0,
- leftIndent = list_indent,
- fontName = 'Times-Bold',
- fontSize = 10,
- leading = 12,
- spaceBefore = 6,
- spaceAfter = 0,
- )
-
- # segment
- list_h3 = styles.ParagraphStyle('ListHeading3', samplestyles['h3'],
- bulletIndent = 0,
- leftIndent = list_indent,
- fontName = 'Times-Italic',
- fontSize = 10,
- leading = 12,
- spaceBefore = 0,
- spaceAfter = 0,
- )
-
- list_text = styles.ParagraphStyle('ListText', samplestyles['Normal'],
- bulletIndent = 0,
- leftIndent = list_indent,
- )
-
- def tree_seq () :
- """
- Tree list numbering
- """
-
- for idx in itertools.count(1) :
- yield "%d." % (idx, )
+ # stylesheet
+ styles = pdf.Styles
# tree root
- tree = ("Sopimusehdot", h2, None, tree_seq(), [
- ("Osapuolet", list_h2, None, tree_seq(), [
- (None, None, "Teekkarispeksi ry (Y-tunnus 1888541-7), jäljempänä “Vuokranantaja”."),
- (None, None, title + u", jäljempänä “Vuokraaja”. 1.1 ja 1.2 jäljempänä yhdessä “osapuolet”.")
+ list_seq = pdf.ListItem.seq
+ tree = pdf.ListItem("Sopimusehdot", styles.h2, None, list_seq(), [
+ pdf.ListItem("Osapuolet", styles.list_h2, None, list_seq(), [
+ pdf.ListItem(None, None, "Teekkarispeksi ry (Y-tunnus 1888541-7), jäljempänä “Vuokranantaja”."),
+ pdf.ListItem(None, None, title + u", jäljempänä “Vuokraaja”. 1.1 ja 1.2 jäljempänä yhdessä “osapuolet”.")
]),
- ("Kaluston lainaaminen", list_h2, None, tree_seq(), [
- ("Yleistä", list_h3, "Tässä sopimuksessa sovitaan toiminnasta Vuokranantajan lainatessa tanssimattoja Vuokraajalle"),
- ("Vuokranantajan velvollisuudet", list_h3, "Vuokranantaja sitoutuu toimittamaan sovittuna ajankohtana Vuokraajalle erikseen sovittava (liite) määrä tanssimattoja."),
- ("Blaa Blaa", list_h3, "Etc."),
+ pdf.ListItem("Kaluston lainaaminen", styles.list_h2, None, list_seq(), [
+ pdf.ListItem("Yleistä", styles.list_h3, "Tässä sopimuksessa sovitaan toiminnasta Vuokranantajan lainatessa tanssimattoja Vuokraajalle"),
+ pdf.ListItem("Vuokranantajan velvollisuudet", styles.list_h3, "Vuokranantaja sitoutuu toimittamaan sovittuna ajankohtana Vuokraajalle erikseen sovittava (liite) määrä tanssimattoja."),
+ pdf.ListItem("Blaa Blaa", styles.list_h3, "Etc."),
]),
- ("Tätä sopimusta ja sitä koskevia erimielisyyksiä koskevat määräykset", list_h2, None, tree_seq(), [
- ("Sopimuksen voimassaolo", list_h3, "Sopimus on osapuolia sitova sen jälkeen, kun osapuolet ovat sen allekirjoittaneet."),
- ("Muutosten tekeminen", list_h3, "Muutokset sopimukseen on tehtävä kirjallisesti molempien osapuolten kesken."),
- ("Blaa Blaa", list_h3, "Etc."),
+ pdf.ListItem("Tätä sopimusta ja sitä koskevia erimielisyyksiä koskevat määräykset", styles.list_h2, None, list_seq(), [
+ pdf.ListItem("Sopimuksen voimassaolo", styles.list_h3, "Sopimus on osapuolia sitova sen jälkeen, kun osapuolet ovat sen allekirjoittaneet."),
+ pdf.ListItem("Muutosten tekeminen", styles.list_h3, "Muutokset sopimukseen on tehtävä kirjallisesti molempien osapuolten kesken."),
+ pdf.ListItem("Blaa Blaa", styles.list_h3, "Etc."),
]),
])
- def fmt_tree (bullet, title, title_style, text, seq=None, sublist=[]) :
- log.debug("bullet(%r) = %r", title, bullet)
-
- # fixed
- text_style = list_text
-
- # first line, with possible bullet
- if title :
- yield rlpp.Paragraph(title, title_style, bullet)
-
- elif text :
- yield rlpp.Paragraph(text, text_style, bullet)
-
- if title and text :
- # indented text after title
- yield rlpp.Paragraph(text, text_style)
-
- if sublist :
- # following lines, indented
- yield rlpp.Indenter(list_indent)
-
- # sub-items
- for item in sublist :
- # get bullet for item
- bullet = next(seq, None) if seq else None
-
- for element in fmt_tree(bullet, *item) :
- yield element
-
- # de-dent
- yield rlpp.Indenter(-list_indent)
-
- class SignatureBlock (rlpp.Flowable) :
-
- # vertical space per field
- FIELD_HEIGHT = 2 * inch / 4
-
- COL_WIDTH_MAX = 4 * inch
-
- PADDING_BOTTOM = inch / 2
-
- def __init__ (self, cols, fields, values) :
- """
- cols - Column titles
- fields - Fields titles, describing the horizontal fields
- values - Pre-filled values as a {(col, field): value} dict
-
- desc/value strings can contain formatting codes:
-
- column - title of the current column
- today - today's date in %d/%m/%Y format
- """
-
- self.cols = cols
- self.fields = fields
- self.values = values
-
- def wrap (self, width, height) :
- """
- Calculate how much space we use up, returning (width, height)
- """
-
- self.width = width
-
- # consume all available height, to place us at the bottom
- self.height = max(len(self.fields) * self.FIELD_HEIGHT, height)
-
- return self.width, self.height
-
- def formatString (self, text, col_title) :
- return text % dict(
- column = col_title,
- today = datetime.date.today().strftime("%d/%m/%Y"),
- )
-
- def draw (self) :
- # target canvas
- canvas = self.canv
-
- col_width = min(self.width / len(self.cols), self.COL_WIDTH_MAX)
- col_margin = col_width * 0.1
- col_height = len(self.fields) * self.FIELD_HEIGHT + self.PADDING_BOTTOM
-
- for field_idx, (field_title) in enumerate(self.fields) :
- h = self.FIELD_HEIGHT
- y = col_height - h * (field_idx + 1)
-
- for col_idx, (col_title) in enumerate(self.cols) :
- w = col_width
- x = w * col_idx
- value = self.values.get((col_title, field_title))
- title = field_title
-
- value = self.formatString(value, col_title) if value else None
- title = self.formatString(title, col_title) if title else None
-
- if value :
- canvas.setFont("Courier-Bold", 14)
- canvas.drawString(x + col_margin + inch / 12, y - h / 2 + 2, value)
-
- # field line
- canvas.line(x + col_margin, y - h / 2, x + w - col_margin, y - h / 2)
-
- # desc text
- canvas.setFont("Times-Italic", 10)
- canvas.drawString(x + col_margin + inch / 8, y - h / 2 - 10, title)
-
+ from reportlab.platypus import Paragraph as p
elements = [
- rlpp.Paragraph("Vuokrasopimus", h1),
- rlpp.Paragraph("Teekkarispeksi ry AV-tekniikka", h3),
- ] + list(fmt_tree(None, *tree)) + [
- rlpp.Paragraph("Nouto", h2),
- rlpp.Paragraph("\t\tAika: _______________\tPaikka: _______________", text),
- rlpp.Paragraph("Palautus", h2),
- rlpp.Paragraph("\t\tAika: _______________\tPaikka: _______________", text),
+ p("Vuokrasopimus", styles.h1),
+ p("Teekkarispeksi ry AV-tekniikka", styles.h3),
+ ] + list(tree.render_pdf()) + [
+ p("Nouto", styles.h2),
+ p("\t\tAika: _______________\tPaikka: _______________", styles.text),
+ p("Palautus", styles.h2),
+ p("\t\tAika: _______________\tPaikka: _______________", styles.text),
- SignatureBlock(("Vuokranantaja", "Vuokraaja"), ("%(column)s", "Nimen selvennys", "Aika ja paikka"), {
+ pdf.SignatureBlock(("Vuokranantaja", "Vuokraaja"), ("%(column)s", "Nimen selvennys", "Aika ja paikka"), {
('Vuokranantaja', 'Nimen selvennys'): "Joel Pirttimaa",
('Vuokranantaja', 'Aika ja paikka'): 'Otaniemi, %(today)s',
('Vuokraaja', 'Aika ja paikka'): 'Otaniemi, %(today)s',
@@ -411,9 +171,9 @@
]
# render elements to buf as PDF code
- doc.build(elements)
+ pdf_code = doc.render_string(elements)
- return Response(buf.getvalue(), mimetype='application/pdf')
+ return Response(pdf_code, mimetype='application/pdf')
class Index (PageHandler) :
DATA = (