AppyPrinciplesGetting started
appy.pod Writing ODT templates The « document » function

The document function, used via the from clause as previously presented, allows you to integrate, into the ODT result, images or files.

Importing images

The following example imports an image from disk.

Parameter at allows to specify the (preferably absolute) path to the image on disk. Note that, in the Python 3 version of Appy, you can place an instance of pathlib.Path in this parameter as well.

The result is the following.

You find this logo ugly? Concentrate yourself on functionality! POD deduced the file type from the file extension. The following file extensions are recognized.

Extension Format
'png' PNG
'jpeg' or 'jpg' JPEG
'gif' GIF
'svg' SVG

By default, the image has been imported anchored as character. If you want to use another anchoring, use parameter anchor. Possible values are strings as-char (as character, the default), char (to character), paragraph (to paragraph) and page (to page).

It is also possible to specify an URL to parameter at. In the following example, an image is imported from a website.

The result is as follows.

Don't be scared, please continue reading!

Historically, there was an alternate way to import images. Instead of using parameter at, a combination of parameters content and format was allowed:

  • parameter content had to store the file's binary content (ie, retrieved by a command like: with open(pythonFile, 'rb') as f: content =;
  • parameter format had to specify the file format, as a string from column "Extension" from the hereabove table.

Although this method still works, it could be removed in the future, so it is not recommended to adopt it for new developments.

When the same image is imported several times in your POD template, POD remembers it and stores a single copy of it within the ODT result.

Importing documents

With the document function, it is also possible to import complete documents within the ODT result. The example below imports the content of another ODT document into the ODT result.

The content of the sub-document to import (sub.odt) is the following.

Here is the result.

As mentioned in the screenshots, LibreOffice is required to run in server mode, behind the scenes. Indeed, this functionality is implemented as follows: POD inserts, in the POD result, a section tied to an external file, and then, asks LibreOffice running in server mode to resolve these sections. Resolving means: re-incorporating, in the master document, the content of sections pointing to external sub-documents.

It is also possible to import PDF documents within the ODT result. For this case, another technique is used: LibreOffice is not required to run in server mode, but Ghostscript will be called to convert the PDF file into one image per page. Then, POD will fallback to the case of importing images into the ODT result.

Suppose we have converted sub.odt to sub.pdf and we have modified the ODT template to import the PDF instead:

The result will be the following.

Here, the result is less subtle: the PDF is splitted into one image per page, and the ODT result contains page-wide images, one per page.

Finally, POD can also incorporate, via the document function, documents in any format that LibreOffice can convert to PDF: doc[x], xls[x], RTF... It is thus possible to write comments like this one:

do text
from document(at='/some/microsoft/word/document.docx')

LibreOffice running in server mode is required for this to work. POD will call it to convert the Word document to PDF; then, POD falls back to the PDF import, will split the PDF into one image per page via Ghostscript and will integrate every image in the ODT result.


The document function, as available in the default POD context, corresponds to method importDocument defined on class Renderer. You will find hereafter the complete function signature, with a detailed explanation of every parameter.

    def importDocument(self, content=None, at=None, format=None,
      anchor='as-char', wrapInPara=True, size=None, sizeUnit='cm',
      maxWidth='page', maxHeight='page', style=None, keepRatio=True,
      pageBreakBefore=False, pageBreakAfter=False, convertOptions=None):
        '''Implements the POD statement "do... from document"'''

        # If at is not None, it represents a path or url allowing to find the
        # document. It can be a string or a pathlib.Path instance. If at is
        # None, the content of the document is supposed to be in binary format
        # in content. The document format may be: odt or any format in
        # imageFormats.

        # anchor, wrapInPara, size, sizeUnit, style and keepRatio
        # are only relevant for images:
        # * anchor defines the way the image is anchored into the document;
        #       valid values are 'page', 'paragraph', 'char' and 'as-char', but
        #       apply only in ODT templates. In an ODS template, implicit anchor
        #       will be "to cell" and anchor will be ignored. In an ODS
        #       template, anchoring "to the page" is currently not supported ;
        # * wrapInPara, if true, wraps the resulting 'image' tag into a 'p'
        #       tag. Do NOT use this when importing an image into an ODS result
        #       via this method. Here is an example of image import ito an ODS
        #       file that will work:
        #         do cell
        #         from+ document(at='/some/path/a.png', wrapInPara=False)
        # * size, if specified, is a tuple of float or integers (width,
        #       height) expressing size in sizeUnit (see below). If not
        #       specified, size will be computed from image info ;
        # * sizeUnit is the unit for size elements, it can be "cm"
        #       (centimeters), "px" (pixels) or "pc" (percentage). Percentages,
        #       in size, must be expressed as integers from 1 to 100 ;
        # * if maxWidth (maxHeight) is specified (as a float value
        #       representing cm), image's width (height) will not be greater
        #       than it. If maxWidth (maxHeight) is "page" (the default),
        #       maxWidth (maxHeight) will be computed as the width of the
        #       main document's page style, margins excluded ;
        # * if style is given, it is a appy.shared.css.CssStyles instance,
        #       containing CSS attributes. If "width" and "heigth" attributes
        #       are found there, they will override size and sizeUnit ;
        # * If keepRatio is True, the image width/height ratio will be kept
        #       when size is specified.

        # pageBreakBefore and pageBreakAfter are only relevant for importing
        # external odt documents, and allows to insert a page break before/after
        # the inserted document. More precisely, each of these parameters can
        # have values:
        # * True     insert a page break;
        # * False    do no insert a page break;
        # moreover, pageBreakAfter can have this additional value:
        # * 'duplex' insert 2 page breaks if the sub-document has an odd number
        #            of pages, 1 else (useful for duplex printing).

        # If convertOptions are given (for images only), imagemagick will be
        # called with these options to perform some transformation on the image.
        # For example, if you specify
        #                    convertOptions="-rotate 90"

        # pod will perform this command before importing the file into the
        # result:
        #               convert your.image -rotate 90 your.image

        # You can also specify a function in convertOptions. This function will
        # receive a single arg, "image", an instance of
        # appy.pod.doc_importers.Image giving some characteristics of the image
        # to convert, like image.width and image.height in pixels (integers). If
        # your function does not return a string containing the convert options,
        # no conversion will occur.

        # Is there something to import ?