Low level API and other recipes

simplejson

web2py includes gluon.contrib.simplejson, developed by Bob Ippolito. This module provides the most standard Python-JSON encoder-decoder.

SimpleJSON consists of two functions:

  • gluon.contrib.simplesjson.dumps(a) encodes a Python object a into JSON.
  • gluon.contrib.simplejson.loads(b) decodes the JSON data in b into a Python object.

Object types that can be serialized include primitive types, lists, and dictionaries. Compound objects can be serialized with the exception of user defined classes.

Here is a sample action (for example in controller “default.py”) that serializes the Python list containing weekdays using this low level API:

  1. def weekdays():
  2. names=['Sunday', 'Monday', 'Tuesday', 'Wednesday',
  3. 'Thursday', 'Friday', 'Saturday']
  4. import gluon.contrib.simplejson
  5. return gluon.contrib.simplejson.dumps(names)

Below is a sample HTML page that sends an Ajax request to the above action, receives the JSON message and stores the list in a corresponding JavaScript variable:

  1. {{extend 'layout.html'}}
  2. <script>
  3. $.getJSON('/application/default/weekdays',
  4. function(data){ alert(data); });
  5. </script>

The code uses the jQuery function $.getJSON, which performs the Ajax call and, on response, stores the weekdays names in a local JavaScript variable data and passes the variable to the callback function. In the example the callback function simply alerts the visitor that the data has been received.

PyRTF

Another common need of web sites is that of generating Word-readable text documents. The simplest way to do so is using the Rich Text Format (RTF) document format. This format was invented by Microsoft and it has since become a standard.

web2py includes gluon.contrib.pyrtf, developed by Simon Cusack and revised by Grant Edwards. This module allows you to generate RTF documents programmatically, including colored formatted text and pictures.

In the following example we initiate two basic RTF classes, Document and Section, append the latter to the former and insert some dummy text in the latter:

  1. def makertf():
  2. import gluon.contrib.pyrtf as q
  3. doc = q.Document()
  4. section = q.Section()
  5. doc.Sections.append(section)
  6. section.append('Section Title')
  7. section.append('web2py is great. ' * 100)
  8. response.headers['Content-Type'] = 'text/rtf'
  9. return q.dumps(doc)

In the end the Document is serialized by q.dumps(doc). Notice that before returning an RTF document it is necessary to specify the content-type in the header else the browser does not know how to handle the file.

Depending on the configuration, the browser may ask you whether to save this file or open it using a text editor.

ReportLab and PDF

web2py can also generate PDF documents, with an additional library called “ReportLab”[ReportLab] .

If you are running web2py from source, it is sufficient to have ReportLab installed. If you are running the Windows binary distribution, you need to unzip ReportLab in the “web2py/“ folder. If you are running the Mac binary distribution, you need to unzip ReportLab in the folder:

  1. web2py.app/Contents/Resources/

From now on we assume ReportLab is installed and that web2py can find it. We will create a simple action called “get_me_a_pdf” that generates a PDF document.

  1. from reportlab.platypus import *
  2. from reportlab.lib.styles import getSampleStyleSheet
  3. from reportlab.rl_config import defaultPageSize
  4. from reportlab.lib.units import inch, mm
  5. from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
  6. from reportlab.lib import colors
  7. from uuid import uuid4
  8. from cgi import escape
  9. import os
  10. def get_me_a_pdf():
  11. title = "This The Doc Title"
  12. heading = "First Paragraph"
  13. text = 'bla ' * 10000
  14. styles = getSampleStyleSheet()
  15. tmpfilename = os.path.join(request.folder, 'private', str(uuid4()))
  16. doc = SimpleDocTemplate(tmpfilename)
  17. story = []
  18. story.append(Paragraph(escape(title), styles["Title"]))
  19. story.append(Paragraph(escape(heading), styles["Heading2"]))
  20. story.append(Paragraph(escape(text), styles["Normal"]))
  21. story.append(Spacer(1,2 * inch))
  22. doc.build(story)
  23. data = open(tmpfilename, "rb").read()
  24. os.unlink(tmpfilename)
  25. response.headers['Content-Type'] = 'application/pdf'
  26. return data

Notice how we generate the PDF into a unique temporary file, tmpfilename, we read the generated PDF from the file, then we deleted the file.

For more information about the ReportLab API, refer to the ReportLab documentation. We strongly recommend using the Platypus API of ReportLab, such as Paragraph, Spacer, etc.