尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Zola 分类法(Taxonomies)模板开发指南:从配置、术语渲染到分页与 Feed 的完整实战

Zola 分类法(Taxonomies)模板开发指南:从配置、术语渲染到分页与 Feed 的完整实战 Zola 分类法Taxonomies模板开发指南从配置、术语渲染到分页与 Feed 的完整实战【免费下载链接】zolaA fast static site generator in a single binary with everything built-in. https://www.getzola.org项目地址: https://gitcode.com/GitHub_Trending/zo/zolaZola 内置的 Taxonomies分类法机制允许你按自定义维度对内容分组并在构建期为每个分类与术语生成独立的列表页、术语页和订阅 Feed。本文将基于 Zola 官方模板文档结合仓库源码与测试站点完整讲解分类法模板的文件查找规则、TaxonomyConfig与TaxonomyTerm的数据结构、list.html与single.html的变量体系以及分页paginator与 Feed 的集成方式让你能直接写出可运行、可复用的分类模板。分类法模板的作用与适用前提在 Zola 中分类法Taxonomy是用户自定义的分类维度术语Term是某个维度下的具体分组而值Value则是被关联到术语的内容条目。构建时Zola 会为每个分类生成两类页面分类列表页列出该分类下的所有术语例如/tags/术语页列出归属于某个术语的所有页面例如/tags/rust/。模板文档明确指出只有在至少一个分类法设置了render true时分类法模板才是必需的。也就是说如果某个分类只用于聚合内容而不需要生成页面例如仅用于 Feed 或内部查询可以关闭渲染反之只要有一个分类需要页面输出就必须提供对应的模板或使用内置回退模板。模板文件的查找规则专用目录与通用回退Zola 会先在templates目录下按分类法名称查找专用模板$TAXONOMY_NAME/single.html分类法名称为子目录$TAXONOMY_NAME/list.html如果找不到则回退到通用模板taxonomy_single.htmltaxonomy_list.html这一点在仓库的渲染实现中有直接印证components/render/src/renderer.rs中渲染术语页时使用cached.single_template.as_deref().unwrap_or(taxonomy_single.html)渲染列表页时使用cached.list_template.as_deref().unwrap_or(taxonomy_list.html)即优先采用按分类法缓存的模板名缺失时回退到通用模板名。在官方文档站点docs/中就能看到实际用法docs/config.toml定义了taxonomies [{ name theme-tags }]对应的专用模板放在docs/templates/theme-tags/目录下single.html与list.html按分类法名组织模板目录。注意模板文件必须放在站点根目录的templates/下主题theme的模板也遵循同样的查找顺序。模板可用的数据类型在编写模板之前需要先理解 Zola 暴露给模板的两个核心类型TaxonomyTerm与TaxonomyConfig。TaxonomyTerm单个术语对象name: String; // 术语名称原始写法如 Guillermo Del Toro slug: String; // 术语的 slug用于 URL如 guillermo-del-toro path: String; // 术语页的路径 permalink: String; // 术语页的完整永久链接 pages: ArrayPage; // 归属于该术语的页面数组 page_count: Number; // 归属于该术语的页面数量从源码components/content/src/taxonomies.rs可以确认TaxonomyTerm内部字段即为name、slug、path、permalink与pages序列化后额外暴露page_count等于item.pages.len()。术语页面的排序由sort_pages(taxo_pages, SortBy::Date)按日期完成无日期的页面会追加到末尾——这符合分类法几乎总是用于博客的定位。TaxonomyConfig分类法的配置对象name: String; // 分类法名称通常用复数如 tags paginate_by: Number?; // 若为正数每个术语页按此数量分页 paginate_path: String?;// 分页路径默认 page页码追加其后 feed: Bool; // 是否为每个术语生成 Feed默认 false render: Bool; // 是否渲染分类与术语页面默认 true源码components/config/src/config/taxonomies.rs中TaxonomyConfig的默认值为paginate_by: None、render: true、feed: falsepaginate_path未设置时默认取page即默认分页链接形如/tags/rust/page/1。同时is_paginated()要求paginate_by必须是大于 0 的数才真正启用分页。分类列表模板list.htmllist.html渲染分类法下的所有术语该模板永远不会被分页因此在所有情况下都获得以下变量config: Config; // 站点配置 taxonomy: TaxonomyConfig; // 该分类法的配置数据 current_url: String; // 当前页面的完整永久链接 current_path: String; // 当前页面的路径 terms: ArrayTaxonomyTerm;// 该分类法下的所有术语 lang: String; // 当前页面语言一个典型的列表模板会遍历terms输出每个术语的名称、数量与链接ul {% for term in terms %} li a href{{ term.permalink | safe }}{{ term.name }}/a ({{ term.page_count }}) /li {% endfor %} /ul仓库测试站点test_site/templates/tags/list.html提供了一个更精简的真实示例{% for tag in terms %} {{ tag.name }} {{ tag.slug }} {{ tag.pages | length }} {% endfor %}可以看到terms中每个元素都具备name、slug、pages等字段与文档声明的TaxonomyTerm结构一致。单个术语模板single.htmlsingle.html渲染某个具体术语下的所有页面获得以下变量config: Config; // 站点配置 taxonomy: TaxonomyConfig; // 该分类法的配置数据 current_url: String; // 当前页面的完整永久链接 current_path: String; // 当前页面的路径 term: TaxonomyTerm; // 当前正在渲染的术语 lang: String; // 当前页面语言如果该术语启用了分页paginate_by为正数模板还会额外获得一个paginator变量其结构与分区section分页完全一致详见 分页模板文档。测试站点test_site/templates/tags/single.html展示了同时兼容分页与非分页的写法{% if not paginator %} Tag: {{ term.name }} {% for page in term.pages %} article h3 classpost__titlea href{{ page.permalink | safe }}{{ page.title | safe }}/a/h3 /article {% endfor %} {% else %} Tag: {{ term.name }} {% for page in paginator.pages %} {{ page.title | safe }} {% endfor %} Num pagers: {{ paginator.number_pagers }} Page size: {{ paginator.paginate_by }} Current index: {{ paginator.current_index }} {% if paginator.previous %}has_prev{% endif %} {% if paginator.next %}has_next{% endif %} {% endif %}关键点在于未分页时页面在term.pages中分页后页面在paginator.pages中模板必须用{% if not paginator %}分流处理。官方文档站点自己的docs/templates/theme-tags/single.html是术语页的真实生产案例它遍历term.pages为每个主题生成卡片链接h1Zola themes in {{ term.name }}/h1 div classthemes {% for theme in term.pages %} a classtheme href{{ theme.permalink }} img src{{ theme.permalink }}screenshot.png altScreenshot of {{ theme.title }} span{{ theme.title }}/span /a {% endfor %} /div这展示了术语页的典型用途term.name作为页面标题term.pages作为内容列表。分页变量paginator分页术语页得到的paginator变量类型为Pager核心字段如下paginate_by: Number; // 每页条目数 base_url: String; // 分页基础 URL可拼接整数得到任意页码链接 number_pagers: Number; // 分页总数 first: String; // 第一页链接 last: String; // 最后一页链接 previous: String?; // 上一页链接若有 next: String?; // 下一页链接若有 pages: ArrayPage; // 当前页的所有页面 current_index: Number; // 当前页码从 1 开始 total_pages: Number; // 全部分页中的页面总数文档明确提醒当paginate_by未设置为正数时paginator变量不会被定义因此模板中必须用{% if paginator %}或{% if not paginator %}进行判空。分页链接的经典写法如下nav classpagination {% if paginator.previous %} a classprevious href{{ paginator.previous }}‹ Previous/a {% endif %} {% if paginator.next %} a classnext href{{ paginator.next }}Next ›/a {% endif %} /nav如果需要给每个分页生成链接可以借助paginator.base_url与paginator.number_pagers拼接{% for i in range(endpaginator.number_pagers) %} a href{{ paginator.base_url }}{{ i 1 }}{{ i 1 }}/a {% endfor %}从配置到输出的完整工作流1. 在配置文件中声明分类法分类法必须声明在zola.toml的主 section即[extra]之外中例如taxonomies [ { name director, feed true }, { name genres, feed true }, { name awards, feed true }, { name release-year, feed true }, ]多语言站点需要同时在对应语言 section 下重复声明taxonomies [ { name director, feed true }, { name genres, feed true }, ] [languages.fr] taxonomies [ { name director, feed true }, { name genres, feed true }, ]这里feed true表示每个术语都会生成 Atom Feed默认格式。2. 在页面 front matter 中标记术语配置完成后在内容页的 front matter 中通过[taxonomies]指定归属 title Shape of water date 2019-08-15 [taxonomies] director [Guillermo Del Toro] genres [Thriller, Drama] awards [Golden Globe, Academy award, BAFTA] release-year [2017] 3. 提供模板并构建创建templates/tags/list.html与templates/tags/single.html或通用回退模板taxonomy_list.html/taxonomy_single.html然后运行zola build即可。仓库渲染器会依次调用render_taxonomy_list与render_taxonomy_term见components/render/src/renderer.rs分别注入terms/term、taxonomy、config、lang、current_url、current_path等变量。输出路径与大小写合并规则分类法页面的输出路径遵循以下规则$BASE_URL/$NAME/ (分类列表页) $BASE_URL/$NAME/$SLUG (术语页)分类法名称从不进行 slugifyURL 中直接使用配置里的name术语会进行 slugify当配置slugify.taxonomies on时这是默认值见 配置文档。若设置了taxonomy_root配置项则所有分类路径都会加上该前缀$BASE_URL/$TAXONOMY_ROOT/$NAME/ (分类列表页) $BASE_URL/$TAXONOMY_ROOT/$NAME/$SLUG (术语页)例如taxonomy_root blog、分类tags、术语rust时分类列表页$BASE_URL/blog/tags/术语页$BASE_URL/blog/tags/rust/该行为在源码测试components/content/src/taxonomies.rs中被直接验证taxonomy_path_with_taxonomy_root断言tax.path /blog/tags/、term.path /blog/tags/rust/而未设置taxonomy_root时路径为/tags/与/tags/rust/。另一个重要规则是分类法不区分大小写slug 相同的术语会被合并。测试merges_terms_with_different_case验证了League of legends与League of Legends两个术语最终合并为唯一一项slug 为league-of-legends且两个页面都被保留。此外如果术语 slugify 后为空字符串例如术语仅含;这类特殊字符构建会直接报错对应测试taxonomy_slug_is_empty_errors因此术语命名应避免纯特殊字符。Feed 与 SEO 最佳实践当分类配置了feed true时Zola 会为每个术语生成 Atom Feed例如/tags/rust/atom.xml订阅者可以只关注特定分类下的内容更新。渲染器中的render_taxonomy_feed见components/render/src/renderer.rs负责这一输出模板层无需额外处理。关于 SEO官方分页文档特别建议不要将分页页面纳入 sitemap因为分页页是非 canonical 页面。在zola.toml中设置exclude_paginated_pages_in_sitemap all即可将全部分页页面从 sitemap 中排除。小结Zola 的分类法模板体系可以总结为一个配置声明、两组模板文件、两类渲染上下文。配置层在主 section 声明taxonomies每个分类可设置name、paginate_by、paginate_path、feed、render、lang模板层按分类名组织$TAXONOMY_NAME/{list,single}.html或使用通用回退模板taxonomy_{list,single}.html数据层list.html拿到全部termssingle.html拿到当前term启用分页时额外获得paginator。掌握这些规则后你既能写出官网主题目录theme-tags那样的术语聚合页也能为博客搭建带分页、带 Feed 的标签系统。更深入的模板变量细节可继续阅读 模板概览、页面与分区模板 与 分页模板 等相关文档。【免费下载链接】zolaA fast static site generator in a single binary with everything built-in. https://www.getzola.org项目地址: https://gitcode.com/GitHub_Trending/zo/zola创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表