Jinja 循环嵌套实战指南:多层与树形数据渲染一次讲透 Jinja 循环嵌套实战指南多层与树形数据渲染一次讲透【免费下载链接】jinjaA very fast and expressive template engine.项目地址: https://gitcode.com/gh_mirrors/ji/jinja接手老项目时我见过最劝退的模板长这样{% for %}套了四层最里层还压着一堆没人敢动的{% if %}改一行怕崩全页。这类多层数据渲染的模板是前后端都头疼的灾区。好在 Jinja 的{% for %}标签、loop对象和recursive递归循环已经把所有控制手柄都备齐了缺的只是知道怎么拿。这篇 Jinja 循环嵌套实战指南就按场景走带你把深模板改薄。【图片占位】Jinja 循环嵌套·树形结构模板渲染效果对比图建议 16:9 横版放一张目录树或评论楼中楼的渲染截图Jinja loop 对象速查7 个常用控制手柄每个{% for %}循环内部都自带一个loop变量这是 Jinja 给模板作者的仪表盘。先用这张速查表认识最常用的几个属性属性作用典型用途loop.index/loop.index0当前轮次从 1 / 从 0编号、行号loop.first/loop.last是否首/末轮加分隔符、收尾标签loop.length序列总长进度提示、x/yloop.depth/loop.depth0递归深度从 1 / 从 0树形缩进、根节点样式loop.previtem/loop.nextitem前一项 / 后一项变化检测、前瞻判断loop.cycle(a, b, ...)按序轮值斑马纹样式loop.changed(x)x 与上一轮是否不同分组标题跨层级怎么拿到外层循环嵌套 for 里loop永远指向最内层并没有loop.parent这种写法。想引用外层得自己先存一份这是个很容易踩的认知坑{% for g in groups %} {% set outer loop %}{# 先把外层循环存下来 #} {% for item in g.items %} {{ outer.index }}-{{ loop.index }} {% endfor %} {% endfor %}这个技巧在后面写递归循环时同样用得上。两层嵌套 for 怎么写以二级侧边栏菜单为例后台侧边栏是最常见的固定两层数据菜单组里挂菜单项。先把两层结构跑通后面的递归才有基础。视图层传进来的是这种结构menu [ {name: 用户管理, children: [{id: 1, name: 用户列表}]}, {name: 系统设置, children: [{id: 2, name: 参数}]}, ]模板里就是朴素的 for 套 forloop会自动指向当前最内层循环ul classsidebar {% for group in menu %} lispan{{ group.name }}/spanul {% for item in group.children %} li>ul classcomments {% for c in comments recursive %} li stylemargin-left: {{ loop.depth0 * 16 }}px b{{ c.author }}/b {{ c.body }} {% if c.replies %}ul{{ loop(c.replies) }}/ul{% endif %} /li {% endfor %} /ulloop.depth0从 0 开始计数正好拿来做每层 16px 的缩进根评论自然顶格。官方文档里的站点地图示例用了同一套写法官方模板文档的 for-loop 一节值得细读循环测试用例里test_recursive一族用例还能帮你确认边界行为。Jinja 模板循环避坑清单性能与可读性这几个坑我基本每个项目都见过按出现频率排了序别找 break/continueJinja 不支持过滤要写在循环条件里{% for u in users if not u.banned %}被跳过的元素不计入loop.index计数反而更准。循环里别干重活排序、聚合、查库都丢回视图层模板只负责怎么摆否则每渲染一次都在重复付账。过深嵌套要控制递归树越深渲染开销越大可以开启字节码缓存见 bccache.py再深的树建议前端分页或异步加载别一次全吐。别在循环里攒变量循环内的赋值在循环结束即被清理想让它活下来是不被支持的行为。调试开debugTrue报错时能看到高亮的模板行号比对着编译产物猜快得多。loop × 过滤器 × 宏组合循环片段这样收口标签墙这种样式轮值 数据过滤 片段复用的场景正好把三种能力叠起来用loop.cycle出斑马纹length过滤器判断热度宏把 li 抽出去给别的模板复用{% macro tag_li(name, count) -%} li{{ name }}small({{ count }})/small/li {%- endmacro %} ul {% for tag in tags %} li class{{ loop.cycle(odd, even) }}{{ tag_li(tag.name, tag.posts | length) }}/li {% endfor %} /ul组合之后你会发现模板里的逻辑不是变多了而是被归位了。如果你手头正有一段 for 套三层的模板不妨今天就动手先看内层能不能改成 recursive再问自己重复片段能不能抽成 macro改完的薄模板会给你正反馈。想再深挖官方模板文档有 loop 全量属性表性能调优技巧讲了编译缓存与模板组织配合 tests/test_core_tags.py 里的循环用例这套 Jinja 递归循环的活基本就练熟了。【免费下载链接】jinjaA very fast and expressive template engine.项目地址: https://gitcode.com/gh_mirrors/ji/jinja创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考