====================
Developer Quickstart
====================

This part of the documentation shows you how to embed Jinja into your
application.

Starting Up
===========

Here the quickest way to create a template from a string and render it:

.. sourcecode:: python

    from jinja import Environment
    env = Environment()
    tmpl = env.from_string('Hello {{ name }}!')
    print tmpl.render(name='John Doe')

This example should output the following string after execution::

    Hello John Doe!

If you receive an error, check if you have a typo in your code. If not, have
a look at the `installation`_ page for troubleshooting.

Basically the important method on a template is the `render` method. It
takes either a dict or keyword arguments. All keyword arguments appear
in the template as variables.

So these two snippets do the same:

.. sourcecode:: python

    tmpl.render(
        knights='we say nih',
        spam='and eggs'
    )

.. sourcecode:: python

    tmpl.render({
        'knights':  'we say nih',
        'spam':     'and eggs'
    })

The Environment
===============

[[environment_doc]]

The environment provides the following useful functions and properties in
addition to the initialization values:

=========================== ==================================================
``parse(source, filename)`` Parse the sourcecode and return the abstract
                            syntax tree. This tree of nodes is used by the
                            `translators`_ to convert the template into
                            executable source- or bytecode.
``lex(source, filename)``   Tokenize the given sourcecode and return a
                            generator of tuples in the form
                            ``(lineno, token, value)``. The filename is just
                            used in the exceptions raised.
                            **New in Jinja 1.1**
``from_string(source)``     Load and parse a template source and translate it
                            into eval-able Python code. This code is wrapped
                            within a `Template` class that allows you to
                            render it.
``get_template(name)``      Load a template from a loader. If the template
                            does not exist, you will get a `TemplateNotFound`
                            exception.
=========================== ==================================================

There are also some internal functions on the environment used by the template
evaluation code to keep it sandboxed.

Undefined Values
================

If a template designer tries to access a not defined value the return value
will be the `undefined_singleton` specified in the environment. The default
one is the `SilentUndefined` which fails in no case. Additionally there is
a special undefined type called the `ComplainingUndefined` which is located
in the `jinja.datastructure` module. It will raise exceptions when compared
with other types, or when rendered.

Theoretically you can provide your own singleton by subclassing
`AbstractUndefindedType` and creating an instance of it using `make_undefined`
(both located in `jinja.datastructure`) but those two types should cover
the basic use cases. The `Undefined` object in that module exists for
backwards compatibility and is an alias for `SilentUndefined`.

To create your own undefined singleton do something like this:

.. sourcecode:: jinja

    from jinja.datastructure import AbstractUndefinedType, make_undefined

    class MyUndefinedType(AbstractUndefindedType):
        __slots__ = ()

        def __iter__(self):
            return iter(int, 0)

        def __reduce__(self):
            return 'MyUndefined'

    MyUndefined = make_undefined(MyUndefinedType)

The only thing you have to do is to override `__reduce__` so that it returns
the name of the singleton instance and create the instance using
`make_undefined`. Everything else is up to you. Note that currently attributes
on undefined objects are available in the Jinja layer too which however
will change in one of the next Jinja versions. So if you put a `foo` attribute
on your undefined singleton you will be able to do ``{{ undefined.foo }}``
by now but certainly not in the future.

This limitation currently exists because undefined is treated as normal object
and thus affected by normal getattr calls.


Automatic Escaping
==================

Jinja provides a way for automatic escaping, but we do not recommend using it.
Because Jinja was designed as multi purpose template engine there are some
issues with automatic escaping. For example filters don't deal with markup
data. Also you can easily bypass the automatic escaping so it's not something
you can expect to "just work". Also there is a huge overhead when escaping
everything.

The best idea is to think about which data already contains html, which will
probably contain (eg: every user input, etc) etc. And live with self escaping.

That's usually a much better idea.


Loading Templates From Files
============================

Loading templates from a string is always a bad idea. It doesn't allow template
inheritance and is also slow since it parses and compiles the template again
and again whereas loaders can cache the template code.

All you have to do is to define a loader and use the `get_template` function.

.. sourcecode:: python

    from jinja import Environment, FileSystemLoader
    env = Environment(loader=FileSystemLoader('templates'))
    tmpl = env.get_template('index.html')
    print tmpl.render(name='John Doe')

This tells jinja to look for templates in the ``templates`` folder. It's a
better idea to use an absolute path here though. For a list of supported
loaders or how to write your own, head over to the `loader`_ documentation.

Adding Filters
==============

If you want to add additional filters to the environment, the best way is to
modify the ``filters`` attribute and not to pass a dict to the environment.
If you pass it a dict it will not include the default filters!

.. sourcecode:: python

    from mylib import my_cool_filter
    env.filters['mycoolfilter'] = my_cool_filter

Writing filter functions is explained in the `filter development`_ section.

Adding Tests
============

Adding additional tests works analogous to filters:

.. sourcecode:: python

    from mylib import my_cool_test
    env.tests['mycooltest'] = my_cool_test

Writing tests is explained in the `test development`_ section.


.. _installation: installation.txt
.. _context documentation: contextenv.txt
.. _loader: loaders.txt
.. _translators: translators.txt
.. _filter development: filters.txt
.. _test development: tests.txt
