Hugo支持从位于hugo项目根目录下的data目录的YAML、JSON或者TOML文件中读取数据

数据目录

data目录是存储hugo 创建站点时hugo使用的其他数据的目录。Data数据文件不用于生成单独页面,他们是内容文件的补充。这个特性在前言设定字段增长太多失去控制时,可以优雅的扩展内容文件。或者可能您想在模板中显示非常大的数据集(参考下面). 这两种情形中,将数据保存在它们自己的文件中都是好主意.

这些文件必须是YAML、JSON、或者TOML格式的文件(使用.yml, .yaml, .json 或者 .toml文件扩展名). 数据可以作为map通过.Site.Data变量访问.

主题中使用数据文件

数据文件也可以使用在Hugo Themes中, 但是请注意主题的数据文件遵循和其他模板数据的Hugo lookup order解析查询顺序相同的逻辑(比如,假设两个文件具有相同的名称和相对路径,在项目根目录的data目录中的文件会具有较高优先级、重载themes/<THEME>/data目录中的数据文件).

因此、主题作者需要注意不要包含可能会很容易被决定定制主题的用户重载的数据文件。对于主题特定的数据单元不应该被重载的,最好使用目录结构的前缀作为命名空间;比如mytheme/data/<THEME>/somekey.... 为检查是否包含这样的重复数据文件,请使用-v标志运行Hugo.

从数据文件中读取的数据模板中创建的字典键是pathfilename、和文件中key(如果可以提取的)的点.链.

使用例子解释最好:

例子:

Jaco Pastorius 是一名伟大的贝斯手, 但是他的个人唱片很短可以作为例子使用. John Patitucci 是另一名贝斯巨匠.

下面的例子编造的有些牵强,但是它很好的展示了数据文件的可适应性. 这个例子使用TOML作为文件格式的下面的两个数据文件:

  • data/jazz/bass/jacopastorius.toml
  • data/jazz/bass/johnpatitucci.toml

文件jacopastorius.toml 包含内容如下, 文件johnpatitucci.toml 包含类似的列表:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
discography = [
"1974 – Modern American Music … Period! The Criteria Sessions",
"1974 – Jaco",
"1976 - Jaco Pastorius",
"1981 - Word of Mouth",
"1981 - The Birthday Concert (released in 1995)",
"1982 - Twins I & II (released in 1999)",
"1983 - Invitation",
"1986 - Broadway Blues (released in 1998)",
"1986 - Honestly Solo Live (released in 1990)",
"1986 - Live In Italy (released in 1991)",
"1986 - Heavy'n Jazz (released in 1992)",
"1991 - Live In New York City, Volumes 1-7.",
"1999 - Rare Collection (compilation)",
"2003 - Punk Jazz: The Jaco Pastorius Anthology (compilation)",
"2007 - The Essential Jaco Pastorius (compilation)"
]

贝斯手的列表可以通过变量 .Site.Data.jazz.bass访问, 单独的贝斯手可以通过在变量后面加上文件名后缀访问, 如.Site.Data.jazz.bass.jacopastorius.

现在可以访问模板中所有贝斯手的唱片列表:

1
2
3
{{ range $.Site.Data.jazz.bass }}
   {{ partial "artist.html" . }}
{{ end }}

然后在文件partials/artist.html中:

1
2
3
4
5
<ul>
{{ range .discography }}
  <li>{{ . }}</li>
{{ end }}
</ul>

发现了另一位喜欢的贝斯手? 只要在相同目录中添加另外一个toml文件.

例子:访问数据文件的有名值

假设您在目录data/中的数据文件User0123.[yml|toml|json] 中具有如下数据结i:

User0123.
     
1
2
3
4
5
6
Achievements:
- Can create a Key, Value list from Data File
- Learns Hugo
- Reads documentation
Name: User0123
Short Description: He is a **jolly good** fellow.
1
2
3
Achievements = ["Can create a Key, Value list from Data File", "Learns Hugo", "Reads documentation"]
Name = "User0123"
"Short Description" = "He is a **jolly good** fellow."
1
2
3
4
5
6
7
8
9
{
   "Achievements": [
      "Can create a Key, Value list from Data File",
      "Learns Hugo",
      "Reads documentation"
   ],
   "Name": "User0123",
   "Short Description": "He is a **jolly good** fellow."
}

可以使用下面代码在布局中呈现Short Description:

1
<div>Short Description of {{.Site.Data.User0123.Name}}: <p>{{ index .Site.Data.User0123 "Short Description" | markdownify }}</p></div>

注意 markdownify 模板函数的使用. 这会将描述文本发送给markdown呈现引擎.

数据驱动的内容

数据文件 特性之外, Hugo 也支持"数据驱动内容" 的特性,此特性使得您可以从几乎任何资源处加载任何JSON 或者 CSV 文件. 数据驱动的内容当前包含两个函数 getJSONgetCSV, 当然这两个函数在所有模板文件中都可用.

实现细节

对URL调用函数

在模板中, 可以这样调用函数:

1
2
{{ $dataJ := getJSON "url" }}
{{ $dataC := getCSV "separator" "url" }}

若果URL使用了后缀或者前缀, 函数接受可变参数 variadic arguments:

1
2
{{ $dataJ := getJSON "url prefix" "arg1" "arg2" "arg n" }}
{{ $dataC := getCSV  "separator" "url prefix" "arg1" "arg2" "arg n" }}

函数getCSV 中使用的分隔符 必须是第一个位置上的参数并且仅有一个字符长.

所有传递的参数会joined连接在一起构建最终的URL:

1
2
{{ $urlPre := "https://api.github.com" }}
{{ $gistJ := getJSON $urlPre "/users/GITHUB_USERNAME/gists" }}

这个会在内部解析成如下的地址:

1
{{ $gistJ := getJSON "https://api.github.com/users/GITHUB_USERNAME/gists" }}

最后, 可以迭代数组。这个例子会输出Github用户的前5个代码段:

1
2
3
4
5
6
7
8
9
<ul>
  {{ $urlPre := "https://api.github.com" }}
  {{ $gistJ := getJSON $urlPre "/users/GITHUB_USERNAME/gists" }}
  {{ range first 5 $gistJ }}
    {{ if .public }}
      <li><a href="{{ .html_url }}" target="_blank">{{ .description }}</a></li>
    {{ end }}
  {{ end }}
</ul>

CSV文件例子

对于 getCSV, 一个字符长的分隔符必须放在跟随URL后面的第一个参数的位置. 下面是从发布的CSV构建的部分模板中创建HTML表格的例子:

layouts/partials/get-csv.html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21

  <table>
    <thead>
      <tr>
      <th>Name</th>
      <th>Position</th>
      <th>Salary</th>
      </tr>
    </thead>
    <tbody>
    {{ $url := "https://example.com/finance/employee-salaries.csv" }}
    {{ $sep := "," }}
    {{ range $i, $r := getCSV $sep $url }}
      <tr>
        <td>{{ index $r 0 }}</td>
        <td>{{ index $r 1 }}</td>
        <td>{{ index $r 2 }}</td>
      </tr>
    {{ end }}
    </tbody>
  </table>

注意必须使用表达式 {{index $r number}} 来输出当前行的第n个列.

缓存

每个下载的URL资源会被缓存在默认的目录$TMPDIR/hugo_cache/. 变量 $TMPDIR 解析为依赖于操作系统的临时目录.

使用命令行参数 --cacheDir, 您可以指定任何系统任何目录作为缓存目录.

也可以在配置文件中 main configuration file设置cacheDir.

如果根本就不喜欢缓存, 可以通过设置命令行参数--ignoreCache 来完全禁用缓存.

使用REST URLS时验证

当前, 仅仅可以填入到URL的认证方法得到支持。 OAuth 和其他认证方法未实现.

加载本地文件

为通过getJSONgetCSV加载本地文件, 源文件必须位于Hugo的工作目录中。文件的扩展名无所谓,文件内容要符合要求.

加载本地文件的输出逻辑同上面调用URL的输出一样。

数据文件热加载

当URL的内容变化时, Hugo没有机会去触发LiveReload 热加载。不过, 当本地 文件变化时(比如data/* and themes/<THEME>/data/*), 会触发热加载. 符号链接不支持热加载. 也请注意下载数据需要一小段时间, Hugo会停止处理markdown文件直到数据下载完毕.

数据驱动内容例子

数据格式规范