- 开发工具
- 前端
- CLI
【免费下载链接】hugo
The world’s fastest framework for building websites.
Site.Data 返回由 data 目录(或挂载到 data 目录的任何目录)中全部文件组装而成的数据结构,是 Hugo 模板中读取站点全局数据的核心入口。本文将围绕该方法(及其在 v0.156.0 起推荐的替代方案 hugo.Data 函数)展开,结合当前 Hugo 仓库源码,讲解其用法、数据组织规则、优先级合并机制与迁移要点。
Site.Data 方法概览
根据 Site.Data 官方文档,该方法签名与返回类型如下:
| 项目 | 说明 |
|---|---|
| 方法名 | Site.Data(模板中使用.Site.Data) |
| 返回类型 | map(Go 中的map[string]any) |
| 签名 | SITE.Data |
| 版本状态 | v0.156.0 起弃用(deprecated),推荐改用hugo.Data函数 |
| 过期时间 | 文档标注 expiryDate 为 2028-02-18 |
在模板中最常见的调用方式是直接链式访问数据键,例如:
{{ range .Site.Data.books }} <li>{{ .title }}</li> {{ end }}从源码看方法实现与弃用链路
在 hugolib/site.go 中,Site.Data的实现非常简短,它只是薄薄的一层包装:
// Returns a map of all the data inside /data. // Deprecated: Use hugo.Data instead. func (s *Site) Data() map[string]any { if !s.isInitialized() { hugo.Deprecate(".Site.Data", "Use hugo.Data instead.", "v0.156.0") } return s.h.Data() }可以看到,源码注释与文档一致:该方法已被标记为弃用,并提示 "Use hugo.Data instead."。当站点尚未初始化时,Hugo 会通过hugo.Deprecate输出弃用警告。实际的数据加载逻辑被下沉到了多站点(HugoSites)层面,也就是说.Site.Data与hugo.Data最终访问的是同一份数据。
底层数据加载机制:loadData 与 handleDataFile
数据加载的核心实现在 hugolib/hugo_sites.go 的loadData方法中:
- 初始化一个空的
map[string]any作为数据根; - 使用
hugofs.NewWalkway遍历PathSpec.BaseFs.Data.Fs(即 data 目录文件系统,包含挂载目录); - 对每个非目录文件调用
handleDataFile递归插入数据树; - 数据按目录层级拆分成键路径,逐层创建嵌套的
map[string]any; - 最终调用
readData,依据文件扩展名通过metadecoders.Default.Unmarshal解析文件内容。
其中readData(hugolib/hugo_sites.go)的关键代码如下:
format := metadecoders.FormatFromString(f.Ext()) return metadecoders.Default.Unmarshal(content, format)也就是说,数据的格式解析完全由文件扩展名决定,支持 JSON、TOML、YAML、XML 等格式。模板通过hugolib/hugo_sites.go中HugoSites.Data()(hugolib/hugo_sites.go)访问这份全局数据,hugo.Data与.Site.Data殊途同归。
数据文件组织与支持格式
官方文档(hugo.Data 文档)给出了一个典型的数据目录结构:
data/ ├── books/ │ ├── fiction.yaml │ └── nonfiction.yaml ├── films.json ├── paintings.xml └── sculptures.tomlHugo 支持的数据格式包括 JSON、TOML、YAML 和 XML。需要特别注意的是:不要将 CSV 文件放入 data 目录。虽然可以通过transform.Unmarshal函数在模板中解析 CSV,但hugo.Data/.Site.Data无法访问 data 目录中的 CSV 文件。
目录名与文件名会被拼接为数据键:例如data/books/fiction.yaml中的顶层键是books,其下是fiction键。这种"目录即键、文件名即键"的规则,让模板可以通过链式标识符(identifier)直接访问,如hugo.Data.books.fiction。
模板中的访问方式与完整示例
沿用文档中的示例数据文件:
- title: The Hunchback of Notre Dame author: Victor Hugo isbn: 978-0140443530 - title: Les Misérables author: Victor Hugo isbn: 978-0451419439- title: The Ancien Régime and the Revolution author: Alexis de Tocqueville isbn: 978-0141441641 - title: Interpreting the French Revolution author: François Furet isbn: 978-0521280495遍历全部数据
{{ range $category, $books := hugo.Data.books }} <p>{{ $category | title }}</p> <ul> {{ range $books }} <li>{{ .title }} ({{ .isbn }})</li> {{ end }} </ul> {{ end }}渲染结果为:
<p>Fiction</p> <ul> <li>The Hunchback of Notre Dame (978-0140443530)</li> <li>Les Misérables (978-0451419439)</li> </ul> <p>Nonfiction</p> <ul> <li>The Ancien Régime and the Revolution (978-0141441641)</li> <li>Interpreting the French Revolution (978-0521280495)</li> </ul>过滤与排序
仅列出虚构类书籍,并按书名排序:
<ul> {{ range sort hugo.Data.books.fiction "title" }} <li>{{ .title }} ({{ .author }})</li> {{ end }} </ul>按 ISBN 精确查找某本书:
{{ range where hugo.Data.books.fiction "isbn" "978-0140443530" }} <li>{{ .title }} ({{ .author }})</li> {{ end }}如果使用弃用前的旧写法,只需将hugo.Data替换为.Site.Data即可获得完全一致的结果。若数据键不是合法标识符(例如包含连字符),则必须使用index函数:
{{ index hugo.Data.books "historical-fiction" }}数据优先级与合并机制(源码级佐证)
数据来源于多个位置(站点 data 目录、主题 data 目录、挂载目录)时,Hugo 遵循"高优先级数据覆盖低优先级数据"的合并规则,具体逻辑见handleDataFile(hugolib/hugo_sites.go):
- map 类型数据:按键逐条合并——若高优先级数据中不存在该键则插入,存在则保留高优先级值,并输出 Info 级别日志;若高优先级数据不是 map(无法合并),则整体覆盖并输出 Warn 日志;
- 数组(
[]any)类型数据:不合并,高优先级数据直接覆盖低优先级数组,并输出 Warn 日志; - 其他类型:输出 Error 日志。
测试用例 hugolib/datafiles_test.go 验证了这一行为:主题mytheme的data/a.toml与站点自身的data/a.toml键冲突时,站点数据胜出(输出a: a_v1);而主题独有的data/d.toml则被保留(输出d: d_v1_theme)。这印证了"主数据目录优先于主题数据目录"的规则。
另外 hugolib/datafiles_test.go 的TestDataMixedCaseFolders表明,大小写混合的目录与文件名(如data/MyFolder/MyData.toml)可以正常通过链式访问(hugo.Data.MyFolder.MyData.v1)。
从 .Site.Data 迁移到 hugo.Data
由于 v0.156.0 已将.Site.Data标记为弃用,新项目应直接使用hugo.Data函数;旧项目迁移时只需机械替换:
- {{ .Site.Data.books }} + {{ hugo.Data.books }}迁移注意事项:
- 数据格式不受影响:JSON、TOML、YAML、XML 的解析逻辑完全相同,因为二者共享
HugoSites.Data()与loadData底层实现; - 数据合并规则不受影响:主题数据、挂载目录数据的优先级行为在两条访问路径下一致;
- 行为差异:
hugo.Data是 v0.156.0 引入的新函数(文档标注new-in 0.156.0),而.Site.Data在站点初始化前访问时会触发弃用警告;.Site.Data的过期移除时间点为 2028-02-18,建议在此前完成迁移。
小结
.Site.Data返回 data 目录组装而成的全局 map,支持 JSON、TOML、YAML、XML,不支持 CSV;- v0.156.0 起推荐使用
hugo.Data,两者共享同一底层加载与合并实现(hugolib/site.go、hugolib/hugo_sites.go); - 目录名与文件名构成链式数据键,非法标识符键需配合
index访问; - 多来源数据遵循"高优先级覆盖、map 按键合并、数组整体覆盖"的规则,主 data 目录优先于主题 data 目录。
相关阅读:Site 方法索引、hugo.Data 函数文档、模块挂载配置。
- 开发工具
- 前端
- CLI
【免费下载链接】hugo
The world’s fastest framework for building websites.
相关推荐
Hugo hugo.Data 函数详解:在模板中访问 data 目录的数据结构
Hugo hugo.Data 函数详解:在模板中访问 data 目录的数据结构 本文围绕 Hugo 的 hugo.Data 函数展开,讲解如何在 Go HTML
开发工具前端CLIHugo Site 方法详解:使用 `.Site.Taxonomies` 获取站点分类数据结构
Hugo Site 方法详解:使用 .Site.Taxonomies 获取站点分类数据结构 Site.Taxonomies 是 Hugo 站点对象上的一个核心方
开发工具前端CLIHugo 图片资源 Exif 元数据提取方法详解:从 `.Exif` 到 `.Meta` 的迁移指南
Hugo 图片资源 Exif 元数据提取方法详解:从 .Exif 到 .Meta 的迁移指南 本指南以 Hugo 图片资源( Resource )上的 Exif
开发工具前端CLI
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考