Appy (Applications in python) is a GPL framework for creating Python web apps.
But faster. A LOT faster!
Grasp its technical principles & psychological effects or download the Appy manifesto.
Download    Forum
To do    Contact
appy.gen – create basic & advanced classes – security & workflows || appy.pod – create basic & advanced templates – render templates.
pod - Rendering templates

Rendering a pod template

In order to render a pod template, the first thing to do is to create a renderer (create a appy.pod.Renderer instance). The constructor for this class looks like this:

class Renderer:
    def __init__(self, template, context, result, pythonWithUnoPath=None,
                 ooPort=2002, stylesMapping={}, forceOoCall=False,
                 finalizeFunction=None, overwriteExisting=False,
        '''This Python Open Document Renderer (PodRenderer) loads a document
        template (p_template) which is an ODT file with some elements
        written in Python. Based on this template and some Python objects
        defined in p_context, the renderer generates an ODT file
        (p_result) that instantiates the p_template and fills it with objects
        from the p_context.

        - If p_result does not end with .odt, the Renderer
           will call LibreOffice to perform a conversion. If p_forceOoCall is
           True, even if p_result ends with .odt, LibreOffice will be called, not
           for performing a conversion, but for updating some elements like
           indexes (table of contents, etc) and sections containing links to
           external files (which is the case, for example, if you use the
           default function "document").

        - If the Python interpreter which runs the current script is not
           UNO-enabled, this script will run, in another process, a UNO-enabled
           Python interpreter (whose path is p_pythonWithUnoPath) which will
           call LibreOffice. In both cases, we will try to connect to LibreOffice
           in server mode on port p_ooPort.

        - If you plan to make "XHTML to OpenDocument" conversions, you may
           specify a styles mapping in p_stylesMapping.

        - If you specify a function in p_finalizeFunction, this function will
           be called by the renderer before re-zipping the ODT result. This way,
           you can still perform some actions on the content of the ODT file
           before it is zipped and potentially converted. This function must
           accept one arg: the absolute path to the temporary folder containing
           the un-zipped content of the ODT result.

        - If you set p_overwriteExisting to True, the renderer will overwrite
           the result file. Else, an exception will be thrown if the result file
           already exists.

        - p_imageResolver allows POD to retrieve images, from "img" tags within
           XHTML content. Indeed, POD may not be able (ie, may not have the
           permission to) perform a HTTP GET on those images. Currently, the
           resolver can only be a Zope application object.

For the template and the result, you can specify absolute or relative paths. I guess it is better to always specify absolute paths.

The context may be either a dict, UserDict, or an instance. If it is an instance, its __dict__ attribute is used. For example, context may be the result of calling globals() or locals(). Every (key, value) pair defined in the context corresponds to a name (the key) that you can use within your template within pod statements or expressions. Those names may refer to any Python object: a function, a variable, an object, a module, etc.

Once you have the Renderer instance, simply call its run method. This method may raise a appy.pod.PodError exception.

Since pod 0.0.2, you may put a XHTML document somewhere in the context and ask pod to convert it as a chunk of OpenDocument into the resulting OpenDocument. You may want to customize the mapping between XHTML and OpenDocument styles. This can be done through the stylesMapping parameter. A detailed explanation about the "XHTML to OpenDocument" abilities of pod may be found here.

Result formats

If result ends with .odt, LibreOffice will NOT be called (unless forceOoCall is True). pod does not need LibreOffice to generate a result in ODT format, excepted in the following cases:

  • you need to update fields in the result (ie a table of contents);
  • you need to include external documents into the result (ODT, PDF, Word, ...) by using special function document.

If result ends with:

  • .pdf,
  • .doc (Microsoft Word 97),
  • .rtf or
  • .txt,

LibreOffice will be called in order to convert a temporary ODT file rendered by pod into the desired format. This will work only if your Python interpreter knows about the Python UNO bindings. UNO is the OpenOffice API. If typing import uno at the interpreter prompt does not produce an error, your interpreter is UNO-enabled. If not, there is probably a UNO-enabled Python interpreter within your LibreOffice copy (in <LibreOfficePath>/program). In this case you can specify this path in the pythonWithUnoPath parameter of the Renderer constructor. Note that when using a UNO-disabled interpreter, there will be one additional process fork for launching a Python-enabled interpreter.

During rendering, pod uses a temp folder located at <result>.temp.

Launching LibreOffice in server mode

You launch LibreOffice in server mode by running the command (under Linux):

soffice -invisible -headless "-accept=socket,host=localhost,port=2002;urp;"

Under Windows it may look like:

"[path_to_lo]\program\soffice" -invisible -headless "-accept=socket,host=localhost,port=2002;urp;"

Of course, use any port number you prefer.