--- doc_id: xDIvlUxVMdDn description: "用 sphinx-jinja 把 Python 数据渲染成 Markdown 表格和 list-table。是一篇模板渲染的演示文档。" tags: [sphinx, jinja] --- # Jinja 模板渲染数据 数据写在 Python 里, 文档里只写模板。数据一改, 重新构建, 所有表格自动更新。 ## 数据从哪来 `conf.py` 把 `sanhe_me_kb.docs.doc_data` 注册成名为 `doc_data` 的 jinja context: ```{literalinclude} ../../conf.py :language: python :start-after: "# -- sphinx-jinja" :end-before: "# -- knowledge base extension" ``` 数据本身是一个 list of tuple: ```{literalinclude} ../../../../sanhe_me_kb/docs/__init__.py :language: python :start-at: "users = [" :end-at: "]" ``` `{jinja}` directive 先用 jinja 渲染它的内容, 再按**当前页面的语法**解析渲染结果: `.md` 页面按 MyST 解析, `.rst` 页面按 reST 解析。 ## 例子 1: Markdown 表格 模板: ````markdown ```{jinja} doc_data | id | name | | :--- | :--- | {% for id, name in doc_data.users -%} | {{ id }} | {{ name }} | {% endfor %} ``` ```` 结果: ```{jinja} doc_data | id | name | | :--- | :--- | {% for id, name in doc_data.users -%} | {{ id }} | {{ name }} | {% endfor %} ``` ## 例子 2: reST list-table 在 `.md` 页面里要输出 reST, 就把渲染结果包在 `{eval-rst}` 里。在 `.rst` 页面里直接写 `.. jinja:: doc_data` 即可, 不需要 `eval-rst`。 模板: `````markdown ````{jinja} doc_data ```{eval-rst} .. list-table:: Users :header-rows: 1 :widths: 10 90 * - id - name {% for id, name in doc_data.users %} * - {{ id }} - {{ name }} {% endfor %} ``` ```` ````` 结果: ````{jinja} doc_data ```{eval-rst} .. list-table:: Users :header-rows: 1 :widths: 10 90 * - id - name {% for id, name in doc_data.users %} * - {{ id }} - {{ name }} {% endfor %} ``` ```` ## 例子 3: 不用 reST 的 list-table MyST 自己也有 `{list-table}` directive, 语法和 reST 一样, 只是外面用 Markdown 的 fence: ````{jinja} doc_data ```{list-table} Users (MyST list-table) :header-rows: 1 * - id - name {% for id, name in doc_data.users -%} * - {{ id }} - {{ name }} {% endfor %} ``` ````