Create Jinja2 macros that put content in separate places
I want to create a table of contents and endnotes in a Jinja2 template. How can one accomplish these tasks?
For example, I want to have a template as follows:
{% block toc %}
{# ... the ToC goes here ... #}
{% endblock %}
{% include "some other file with content.jnj" %}
{% block endnotes %}
{# ... the endnotes go here ... #}
{% endblock %}
Where the some other file with content.jnj
has content like this:
{% section "One" %}
Title information for Section One (may be quite long); goes in Table of Contents
...
Content of section One
{% section "Two" %}
Title inform开发者_JS百科ation of Section Two (also may be quite long)
<a href="#" id="en1">EndNote 1</a>
<script type="text/javsacript">...(may be reasonably long)
</script> {# ... Everything up to here is included in the EndNote #}
Where I say "may be quite/reasonably long" I mean to say that it can't reasonably be put into quotes as an argument to a macro or global function.
I'm wondering if there's a pattern for this that may accommodate this, within the framework of Jinja2.
My initial thought is to create an extension, so that one can have a block for sections and end-notes, like-so:
{% section "One" %}
Title information goes here.
{% endsection %}
{% endnote "one" %}
<a href="#">...</a>
<script> ... </script>
{% endendnote %}
Then have global functions (that pass in the Jinja2 Environment):
{{ table_of_contents() }}
{% include ... %}
{{ endnotes() }}
However, while this will work for endnotes, I'd presume it requires a second pass by something for the table of contents.
Thank you for reading. I'd be much obliged for your thoughts and input.
Brian
Seems like you are heading down the right path in defining a consistent structure for each section (i.e title, body, endnotes). Would storing this information in regular Python data structures - rather than Jinja blocks and/or custom extensions - be acceptable? Example below.
in content.jnj
:
{% set sections = [] %}
{% do sections.append({
'title': 'Section One title',
'body':
"""
Section one main body text...
""",
'endnotes':
"""
<a href='#'>...</a>
<script> ... </script>
""",
})
%}
{# append more sections #}
in template.jnj
:
{% from 'content.jnj' import sections as sections %}
{# table of contents #}
{% for section in sections %}
{{ loop.index }}. {{ section['title'] }}
{% endfor %}
{# body #}
{% for section in sections %}
{{ section['title'] }}
{{ section['body'] }}
{% endfor %}
{# endnotes #}
{% for section in sections %}
{{ loop.index }}. {{ section['endnotes'] }}
{% endfor %}
Note that content.jnj
requires the Jinja2 do
extension to be enabled (e.g. env = jinja2.Environment(extensions=['jinja2.ext.do'])
.)
It may be overkill for your purposes, but another option is to store the content in a markup language, such as reStructuredText, and design the presentation layer as a Sphinx theme (Jinja2 is the default template format).
精彩评论