Skip to content

Commit

Permalink
Add support for Jinja2 global namespace
Browse files Browse the repository at this point in the history
Closes #69.
Closes #70.
  • Loading branch information
TimBest authored and Ceasar committed Aug 19, 2016
1 parent 675f6a3 commit 3476a39
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 21 deletions.
1 change: 1 addition & 0 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ Patches and Suggestions
- Bryan Bennett (bbenne10)
- Anuraag Agrawal (anuraaga)
- saschalalala
- Tim Best (timbest)
52 changes: 33 additions & 19 deletions docs/user/advanced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,42 +63,56 @@ Loading data
Some applications render templates based on data sources (e.g. CSVs or
JSON files).

The simplest way to get data to templates is to set up a mapping from
filenames to dictionaries representing the data ("contexts"). For example, the
following code block passes some data to a template named "index.html":
The simplest way to supply data to templates is to pass ``make_site()`` a
mapping from variable names to their values (a "context") as the ``env_globals``
keyword argument.

.. code-block:: python
if __name__ == "__main__":
site = staticjinja.make_site(env_globals={
'greeting':'Hello world!',
})
site.render()
Anything added to this dictionary will be available in all templates:

.. code-block:: html

<!-- templates/index.html -->
<h1>{{greeting}}</h1>

If the context needs to be different for each template, you can restrict
contexts to certain templates by supplying ``make_site()`` a sequence of
regex-context pairs as the ``contexts`` keyword argument. When rendering a
template, staticjinja will search this sequence for the first regex that matches
the template's name, and use that context to interpolate variables. For example,
the following code block supplies a context to the template named "index.html":

.. code-block:: python
from staticjinja import make_site
if __name__ == "__main__":
site = make_site(contexts=[('index.html', {
'knights': ['sir arthur', 'sir lancelot', 'sir galahad']
})])
context = {'knights': ['sir arthur', 'sir lancelot', 'sir galahad']}
site = make_site(contexts=[('index.html', context)])
site.render()
You can then use the data in ``templates/index.html`` as you'd expect:

.. code-block:: html

<!-- templates/index.html -->
{% extends "_base.html" %}
{% block body %}
<h1>Hello world!</h1>
<p>This is an example web page.</p>
<h3>Knights of the Round Table</h3>
<h1>Knights of the Round Table</h1>
<ul>
{% for knight in knights %}
<li>{{ knight }}</li>
{% endfor %}
</ul>
{% endblock %}

For more complex situations, you can map filenames to functions that return a
dictionary ("context generators"). Context generators may either take no
arguments or the current template as its sole argument. For example, the
following code adds the modification time of the template file to the context of
any templates with an HTML extension:
If contexts needs to be generated dynamically, you can associate filenames with
functions that return a context ("context generators"). Context generators may
either take no arguments or the current template as its sole argument. For
example, the following code creates a context with the last modification time of
the template file for any templates with an HTML extension:

.. code-block:: python
Expand Down
11 changes: 9 additions & 2 deletions staticjinja/staticjinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ def make_site(searchpath="templates",
extensions=None,
staticpaths=None,
filters=None,
env_globals=None,
env_kwargs=None,
mergecontexts=False):
"""Create a :class:`Site <Site>` object.
Expand Down Expand Up @@ -382,6 +383,10 @@ def make_site(searchpath="templates",
A dictionary of Jinja2 filters to add to the Environment.
Defaults to ``{}``.
:param env_globals:
A mapping from variable names that should be available all the time to
their values. Defaults to ``{}``.
:param env_kwargs:
A dictionary that will be passed as keyword arguments to the
jinja2 Environment. Defaults to ``{}``.
Expand Down Expand Up @@ -409,8 +414,10 @@ def make_site(searchpath="templates",
env_kwargs.setdefault('extensions', extensions or [])
environment = Environment(**env_kwargs)
if filters:
for k, v in filters.items():
environment.filters[k] = v
environment.globals.update(filters)

This comment has been minimized.

Copy link
@michilu

michilu Sep 11, 2016

The filters do not work.
I seem like a bug.
#73


if env_globals:
environment.globals.update(env_globals)

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
Expand Down
11 changes: 11 additions & 0 deletions test_staticjinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,17 @@ def test_render_nested_template(site, build_path):
assert template3.read() == "Test 3"


def test_render_template_with_env_globals(template_path, build_path):
"""Ensure variables defined in env_globals can be accessed globally."""
template_name = 'template.html'
template_path.join(template_name).write('<h1>{{greeting}}</h1>')
site = make_site(searchpath=str(template_path),
outpath=str(build_path),
env_globals={'greeting': 'Hello world!'})
site.render_template(site.get_template(template_name))
assert build_path.join(template_name).read() == '<h1>Hello world!</h1>'


def test_render_templates(site, build_path):
site.render_templates(site.templates)
template1 = build_path.join("template1.html")
Expand Down

0 comments on commit 3476a39

Please sign in to comment.