4.2 模板的製作:Jinja2模板中的遞歸

4.2 模板的製作:Jinja2模板中的遞歸

來自專欄報告自動化生成

學習目標

  • 使用jinja2模板的遞歸方法重構報告生成模板

前期設置

  • 初始化document
  • 定義直接顯示jinja2渲染結果的函數render_templ

Recursive Example For Jinja2

首先我們來看一個Jinja2模板的遞歸例子,需要注意此時的渲染方式有變化,需要提前設置環境。

import jinja2template = """{%- 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 = childrensitemap = [ 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

推薦閱讀:

遞歸:夢中夢
遞歸函數(二):編寫遞歸函數的思路和技巧
具體數學-第1課(遞歸求解實際問題)
POJ 2694:逆波蘭表達式

TAG:遞歸 | 高效工作 | 數據報告 |