1.. _usage_toplevel: 2 3===== 4Usage 5===== 6 7Basic Usage 8=========== 9 10This section describes the Python API for Mako templates. If you 11are using Mako within a web framework such as Pylons, the work 12of integrating Mako's API is already done for you, in which case 13you can skip to the next section, :ref:`syntax_toplevel`. 14 15The most basic way to create a template and render it is through 16the :class:`.Template` class: 17 18.. sourcecode:: python 19 20 from mako.template import Template 21 22 mytemplate = Template("hello world!") 23 print(mytemplate.render()) 24 25Above, the text argument to :class:`.Template` is **compiled** into a 26Python module representation. This module contains a function 27called ``render_body()``, which produces the output of the 28template. When ``mytemplate.render()`` is called, Mako sets up a 29runtime environment for the template and calls the 30``render_body()`` function, capturing the output into a buffer and 31returning its string contents. 32 33 34The code inside the ``render_body()`` function has access to a 35namespace of variables. You can specify these variables by 36sending them as additional keyword arguments to the :meth:`~.Template.render` 37method: 38 39.. sourcecode:: python 40 41 from mako.template import Template 42 43 mytemplate = Template("hello, ${name}!") 44 print(mytemplate.render(name="jack")) 45 46The :meth:`~.Template.render` method calls upon Mako to create a 47:class:`.Context` object, which stores all the variable names accessible 48to the template and also stores a buffer used to capture output. 49You can create this :class:`.Context` yourself and have the template 50render with it, using the :meth:`~.Template.render_context` method: 51 52.. sourcecode:: python 53 54 from mako.template import Template 55 from mako.runtime import Context 56 from io import StringIO 57 58 mytemplate = Template("hello, ${name}!") 59 buf = StringIO() 60 ctx = Context(buf, name="jack") 61 mytemplate.render_context(ctx) 62 print(buf.getvalue()) 63 64Using File-Based Templates 65========================== 66 67A :class:`.Template` can also load its template source code from a file, 68using the ``filename`` keyword argument: 69 70.. sourcecode:: python 71 72 from mako.template import Template 73 74 mytemplate = Template(filename='/docs/mytmpl.txt') 75 print(mytemplate.render()) 76 77For improved performance, a :class:`.Template` which is loaded from a 78file can also cache the source code to its generated module on 79the filesystem as a regular Python module file (i.e. a ``.py`` 80file). To do this, just add the ``module_directory`` argument to 81the template: 82 83.. sourcecode:: python 84 85 from mako.template import Template 86 87 mytemplate = Template(filename='/docs/mytmpl.txt', module_directory='/tmp/mako_modules') 88 print(mytemplate.render()) 89 90When the above code is rendered, a file 91``/tmp/mako_modules/docs/mytmpl.txt.py`` is created containing the 92source code for the module. The next time a :class:`.Template` with the 93same arguments is created, this module file will be 94automatically re-used. 95 96.. _usage_templatelookup: 97 98Using ``TemplateLookup`` 99======================== 100 101All of the examples thus far have dealt with the usage of a 102single :class:`.Template` object. If the code within those templates 103tries to locate another template resource, it will need some way 104to find them, using simple URI strings. For this need, the 105resolution of other templates from within a template is 106accomplished by the :class:`.TemplateLookup` class. This class is 107constructed given a list of directories in which to search for 108templates, as well as keyword arguments that will be passed to 109the :class:`.Template` objects it creates: 110 111.. sourcecode:: python 112 113 from mako.template import Template 114 from mako.lookup import TemplateLookup 115 116 mylookup = TemplateLookup(directories=['/docs']) 117 mytemplate = Template("""<%include file="header.txt"/> hello world!""", lookup=mylookup) 118 119Above, we created a textual template which includes the file 120``"header.txt"``. In order for it to have somewhere to look for 121``"header.txt"``, we passed a :class:`.TemplateLookup` object to it, which 122will search in the directory ``/docs`` for the file ``"header.txt"``. 123 124Usually, an application will store most or all of its templates 125as text files on the filesystem. So far, all of our examples 126have been a little bit contrived in order to illustrate the 127basic concepts. But a real application would get most or all of 128its templates directly from the :class:`.TemplateLookup`, using the 129aptly named :meth:`~.TemplateLookup.get_template` method, which accepts the URI of the 130desired template: 131 132.. sourcecode:: python 133 134 from mako.template import Template 135 from mako.lookup import TemplateLookup 136 137 mylookup = TemplateLookup(directories=['/docs'], module_directory='/tmp/mako_modules') 138 139 def serve_template(templatename, **kwargs): 140 mytemplate = mylookup.get_template(templatename) 141 print(mytemplate.render(**kwargs)) 142 143In the example above, we create a :class:`.TemplateLookup` which will 144look for templates in the ``/docs`` directory, and will store 145generated module files in the ``/tmp/mako_modules`` directory. The 146lookup locates templates by appending the given URI to each of 147its search directories; so if you gave it a URI of 148``/etc/beans/info.txt``, it would search for the file 149``/docs/etc/beans/info.txt``, else raise a :class:`.TopLevelNotFound` 150exception, which is a custom Mako exception. 151 152When the lookup locates templates, it will also assign a ``uri`` 153property to the :class:`.Template` which is the URI passed to the 154:meth:`~.TemplateLookup.get_template()` call. :class:`.Template` uses this URI to calculate the 155name of its module file. So in the above example, a 156``templatename`` argument of ``/etc/beans/info.txt`` will create a 157module file ``/tmp/mako_modules/etc/beans/info.txt.py``. 158 159Setting the Collection Size 160--------------------------- 161 162The :class:`.TemplateLookup` also serves the important need of caching a 163fixed set of templates in memory at a given time, so that 164successive URI lookups do not result in full template 165compilations and/or module reloads on each request. By default, 166the :class:`.TemplateLookup` size is unbounded. You can specify a fixed 167size using the ``collection_size`` argument: 168 169.. sourcecode:: python 170 171 mylookup = TemplateLookup(directories=['/docs'], 172 module_directory='/tmp/mako_modules', collection_size=500) 173 174The above lookup will continue to load templates into memory 175until it reaches a count of around 500. At that point, it will 176clean out a certain percentage of templates using a least 177recently used scheme. 178 179Setting Filesystem Checks 180------------------------- 181 182Another important flag on :class:`.TemplateLookup` is 183``filesystem_checks``. This defaults to ``True``, and says that each 184time a template is returned by the :meth:`~.TemplateLookup.get_template()` method, the 185revision time of the original template file is checked against 186the last time the template was loaded, and if the file is newer 187will reload its contents and recompile the template. On a 188production system, setting ``filesystem_checks`` to ``False`` can 189afford a small to moderate performance increase (depending on 190the type of filesystem used). 191 192.. _usage_unicode: 193 194Using Unicode and Encoding 195========================== 196 197Both :class:`.Template` and :class:`.TemplateLookup` accept ``output_encoding`` 198and ``encoding_errors`` parameters which can be used to encode the 199output in any Python supported codec: 200 201.. sourcecode:: python 202 203 from mako.template import Template 204 from mako.lookup import TemplateLookup 205 206 mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace') 207 208 mytemplate = mylookup.get_template("foo.txt") 209 print(mytemplate.render()) 210 211When using Python 3, the :meth:`~.Template.render` method will return a ``bytes`` 212object, **if** ``output_encoding`` is set. Otherwise it returns a 213``string``. 214 215Additionally, the :meth:`~.Template.render_unicode()` method exists which will 216return the template output as a Python ``unicode`` object, or in 217Python 3 a ``string``: 218 219.. sourcecode:: python 220 221 print(mytemplate.render_unicode()) 222 223The above method disregards the output encoding keyword 224argument; you can encode yourself by saying: 225 226.. sourcecode:: python 227 228 print(mytemplate.render_unicode().encode('utf-8', 'replace')) 229 230Note that Mako's ability to return data in any encoding and/or 231``unicode`` implies that the underlying output stream of the 232template is a Python unicode object. This behavior is described 233fully in :ref:`unicode_toplevel`. 234 235.. _handling_exceptions: 236 237Handling Exceptions 238=================== 239 240Template exceptions can occur in two distinct places. One is 241when you **lookup, parse and compile** the template, the other 242is when you **run** the template. Within the running of a 243template, exceptions are thrown normally from whatever Python 244code originated the issue. Mako has its own set of exception 245classes which mostly apply to the lookup and lexer/compiler 246stages of template construction. Mako provides some library 247routines that can be used to help provide Mako-specific 248information about any exception's stack trace, as well as 249formatting the exception within textual or HTML format. In all 250cases, the main value of these handlers is that of converting 251Python filenames, line numbers, and code samples into Mako 252template filenames, line numbers, and code samples. All lines 253within a stack trace which correspond to a Mako template module 254will be converted to be against the originating template file. 255 256To format exception traces, the :func:`.text_error_template` and 257:func:`.html_error_template` functions are provided. They make usage of 258``sys.exc_info()`` to get at the most recently thrown exception. 259Usage of these handlers usually looks like: 260 261.. sourcecode:: python 262 263 from mako import exceptions 264 265 try: 266 template = lookup.get_template(uri) 267 print(template.render()) 268 except: 269 print(exceptions.text_error_template().render()) 270 271Or for the HTML render function: 272 273.. sourcecode:: python 274 275 from mako import exceptions 276 277 try: 278 template = lookup.get_template(uri) 279 print(template.render()) 280 except: 281 print(exceptions.html_error_template().render()) 282 283The :func:`.html_error_template` template accepts two options: 284specifying ``full=False`` causes only a section of an HTML 285document to be rendered. Specifying ``css=False`` will disable the 286default stylesheet from being rendered. 287 288E.g.: 289 290.. sourcecode:: python 291 292 print(exceptions.html_error_template().render(full=False)) 293 294The HTML render function is also available built-in to 295:class:`.Template` using the ``format_exceptions`` flag. In this case, any 296exceptions raised within the **render** stage of the template 297will result in the output being substituted with the output of 298:func:`.html_error_template`: 299 300.. sourcecode:: python 301 302 template = Template(filename="/foo/bar", format_exceptions=True) 303 print(template.render()) 304 305Note that the compile stage of the above template occurs when 306you construct the :class:`.Template` itself, and no output stream is 307defined. Therefore exceptions which occur within the 308lookup/parse/compile stage will not be handled and will 309propagate normally. While the pre-render traceback usually will 310not include any Mako-specific lines anyway, it will mean that 311exceptions which occur previous to rendering and those which 312occur within rendering will be handled differently... so the 313``try``/``except`` patterns described previously are probably of more 314general use. 315 316The underlying object used by the error template functions is 317the :class:`.RichTraceback` object. This object can also be used 318directly to provide custom error views. Here's an example usage 319which describes its general API: 320 321.. sourcecode:: python 322 323 from mako.exceptions import RichTraceback 324 325 try: 326 template = lookup.get_template(uri) 327 print(template.render()) 328 except: 329 traceback = RichTraceback() 330 for (filename, lineno, function, line) in traceback.traceback: 331 print("File %s, line %s, in %s" % (filename, lineno, function)) 332 print(line, "\n") 333 print("%s: %s" % (str(traceback.error.__class__.__name__), traceback.error)) 334 335Common Framework Integrations 336============================= 337 338The Mako distribution includes a little bit of helper code for 339the purpose of using Mako in some popular web framework 340scenarios. This is a brief description of what's included. 341 342WSGI 343---- 344 345A sample WSGI application is included in the distribution in the 346file ``examples/wsgi/run_wsgi.py``. This runner is set up to pull 347files from a `templates` as well as an `htdocs` directory and 348includes a rudimental two-file layout. The WSGI runner acts as a 349fully functional standalone web server, using ``wsgiutils`` to run 350itself, and propagates GET and POST arguments from the request 351into the :class:`.Context`, can serve images, CSS files and other kinds 352of files, and also displays errors using Mako's included 353exception-handling utilities. 354 355Pygments 356-------- 357 358A `Pygments <https://pygments.org/>`_-compatible syntax 359highlighting module is included under :mod:`mako.ext.pygmentplugin`. 360This module is used in the generation of Mako documentation and 361also contains various `setuptools` entry points under the heading 362``pygments.lexers``, including ``mako``, ``html+mako``, ``xml+mako`` 363(see the ``setup.py`` file for all the entry points). 364 365Babel 366----- 367 368Mako provides support for extracting `gettext` messages from 369templates via a `Babel`_ extractor 370entry point under ``mako.ext.babelplugin``. 371 372`Gettext` messages are extracted from all Python code sections, 373including those of control lines and expressions embedded 374in tags. 375 376`Translator 377comments <http://babel.edgewall.org/wiki/Documentation/messages.html#comments-tags-and-translator-comments-explanation>`_ 378may also be extracted from Mako templates when a comment tag is 379specified to `Babel`_ (such as with 380the ``-c`` option). 381 382For example, a project ``"myproj"`` contains the following Mako 383template at ``myproj/myproj/templates/name.html``: 384 385.. sourcecode:: mako 386 387 <div id="name"> 388 Name: 389 ## TRANSLATORS: This is a proper name. See the gettext 390 ## manual, section Names. 391 ${_('Francois Pinard')} 392 </div> 393 394To extract gettext messages from this template the project needs 395a Mako section in its `Babel Extraction Method Mapping 396file <http://babel.edgewall.org/wiki/Documentation/messages.html#extraction-method-mapping-and-configuration>`_ 397(typically located at ``myproj/babel.cfg``): 398 399.. sourcecode:: cfg 400 401 # Extraction from Python source files 402 403 [python: myproj/**.py] 404 405 # Extraction from Mako templates 406 407 [mako: myproj/templates/**.html] 408 input_encoding = utf-8 409 410The Mako extractor supports an optional ``input_encoding`` 411parameter specifying the encoding of the templates (identical to 412:class:`.Template`/:class:`.TemplateLookup`'s ``input_encoding`` parameter). 413 414Invoking `Babel`_'s extractor at the 415command line in the project's root directory: 416 417.. sourcecode:: sh 418 419 myproj$ pybabel extract -F babel.cfg -c "TRANSLATORS:" . 420 421will output a `gettext` catalog to `stdout` including the following: 422 423.. sourcecode:: pot 424 425 #. TRANSLATORS: This is a proper name. See the gettext 426 #. manual, section Names. 427 #: myproj/templates/name.html:5 428 msgid "Francois Pinard" 429 msgstr "" 430 431This is only a basic example: 432`Babel`_ can be invoked from ``setup.py`` 433and its command line options specified in the accompanying 434``setup.cfg`` via `Babel Distutils/Setuptools 435Integration <http://babel.edgewall.org/wiki/Documentation/setup.html>`_. 436 437Comments must immediately precede a `gettext` message to be 438extracted. In the following case the ``TRANSLATORS:`` comment would 439not have been extracted: 440 441.. sourcecode:: mako 442 443 <div id="name"> 444 ## TRANSLATORS: This is a proper name. See the gettext 445 ## manual, section Names. 446 Name: ${_('Francois Pinard')} 447 </div> 448 449See the `Babel User 450Guide <http://babel.edgewall.org/wiki/Documentation/index.html>`_ 451for more information. 452 453.. _babel: http://babel.edgewall.org/ 454 455 456API Reference 457============= 458 459.. autoclass:: mako.template.Template 460 :show-inheritance: 461 :members: 462 463.. autoclass:: mako.template.DefTemplate 464 :show-inheritance: 465 :members: 466 467.. autoclass:: mako.lookup.TemplateCollection 468 :show-inheritance: 469 :members: 470 471.. autoclass:: mako.lookup.TemplateLookup 472 :show-inheritance: 473 :members: 474 475.. autoclass:: mako.exceptions.RichTraceback 476 :show-inheritance: 477 478 .. py:attribute:: error 479 480 the exception instance. 481 482 .. py:attribute:: message 483 484 the exception error message as unicode. 485 486 .. py:attribute:: source 487 488 source code of the file where the error occurred. 489 If the error occurred within a compiled template, 490 this is the template source. 491 492 .. py:attribute:: lineno 493 494 line number where the error occurred. If the error 495 occurred within a compiled template, the line number 496 is adjusted to that of the template source. 497 498 .. py:attribute:: records 499 500 a list of 8-tuples containing the original 501 python traceback elements, plus the 502 filename, line number, source line, and full template source 503 for the traceline mapped back to its originating source 504 template, if any for that traceline (else the fields are ``None``). 505 506 .. py:attribute:: reverse_records 507 508 the list of records in reverse 509 traceback -- a list of 4-tuples, in the same format as a regular 510 python traceback, with template-corresponding 511 traceback records replacing the originals. 512 513 .. py:attribute:: reverse_traceback 514 515 the traceback list in reverse. 516 517.. autofunction:: mako.exceptions.html_error_template 518 519.. autofunction:: mako.exceptions.text_error_template 520