报告自动化生成

4.2 模板的制作:Jinja2模板中的递归

2018-07-31  本文已影响17人  数据成长之路

学习目标

前期设置

Recursive Example For Jinja2

首先我们来看一个Jinja2模板的递归例子,需要注意此时的渲染方式有变化,需要提前设置环境。

import jinja2

template = """
{%- set idxs = [0] -%}
{%- for item in sitemap recursive %}
    depth={{idxs|length}}. idx={{loop.index}}. pidx={{idxs[-1]}}. title={{item.title}}
    {%- if item.children -%}
        {%- do idxs.append(loop.index) -%}
        {{ loop(item.children) }}
        {%- do idxs.pop() -%}
    {%- endif %}
{%- endfor %}
"""

class Node():
    def __init__(self, title, children=[]):
        self.title = title
        self.children = children

sitemap = [
    Node('a', [
        Node('a_a', [
            Node('a_a_a'),
            ]),
        Node('a_b', [
            Node('a_b_a', [
                Node('a_b_a_0'),
                ]),
            ]),
        ]),
    Node('b'),
    ]

env = jinja2.Environment(extensions=['jinja2.ext.do'])
print(env.from_string(template).render(sitemap=sitemap))
    depth=1. idx=1. pidx=0. title=a
    depth=2. idx=1. pidx=1. title=a_a
    depth=3. idx=1. pidx=1. title=a_a_a
    depth=2. idx=2. pidx=1. title=a_b
    depth=3. idx=1. pidx=2. title=a_b_a
    depth=4. idx=1. pidx=1. title=a_b_a_0
    depth=1. idx=2. pidx=0. title=b

把之前生成报告的模板改为使用递归的形式

而我们的Docoment类同样是一个树结构,可以进行递归的模板生成。而且每个Chapter和SubChapter都有着类似的结构,可以使用同样的处理方式,所以可以把我们之前的jinja2模板改为:

<body>
<section class = "rich-text">
<h1>{{ document.title }}</h1>
<p>{{ document.foreword }}</p>

{% for chapter in document.chapters recursive %}
    {%- if not chapter.title is none %}
        <h2>{{ chapter.title }}</h2>
    {%- endif -%}
    {%- if not chapter.foreword is none %}
        <p>{{ chapter.foreword }}</p>
    {%- endif -%}
    {% if not chapter.table is none %}
    {% set table = chapter.table %}
        <table>
            <tr class='chapter_table'>
            {% for column in table.columns %}
            <th>{{column}}</th>
            {% endfor %}
            </tr>
            {% for index in table.index %}
                <tr>
                {% for column in table.columns %}
                    <td>{{ table[column][index] }}</td>
                {% endfor %}
                </tr>
            {% endfor %}
        </table>
    {% endif %}
    {% if not chapter.image is none %}
        {% set image = chapter.image %}
        <div><img src="{{ image }}"></div>
    {% endif %}
    {% if not chapter.content is none %}
        <p>{{ chapter.content }}</p>
    {% endif %}
    {% if chapter.chapters.__len__() > 0 %}
        {{ loop(chapter.chapters) }}
    {% endif %}

{% endfor %}
</section>
</body>

作业

上面的递归会把所有的章标题记录为<h2>,对于更深一层的子章节我们需要使用更小的标签,比如<h3>,这时候就可以使用递归深度来做规定。请自行做出作为练习。
想要直接查看结果可以参照Example_3


上一篇 下一篇

猜你喜欢

热点阅读