I have data files with filenames set to the same as the content files they relate to, for example:
content / post / content-item.md
data / content-item.toml
I need to have this set-up as the data files are auto-generated from an API (usually I’d put this info into the page param).
What I’ve been doing is having a param in the data file such as post = "content-item"
and looping through the data files, comparing the post param to the slug on the content item in order to render out the correct file contents. This works fine, but I’d like to get rid of the requirement of the additional param.
Is there a way of filtering {{ range .Site.Data }} based on the slug directly?
(In existing example terms as on http://gohugo.io/extras/datafiles/ I’d like get a specific discography based on a filename set in a variable).
…and in the Front Matter for content/places/first.md I would specify
data_name = "foo"
However it doesn’t work, and gives me this error:
ERROR: (...) error calling where: can't iterate over map[string]interface {}
What I really want to do, like @adamliptrot, is get the struct for a data file by name (sans extension), so I don’t have to bother with the “data_name” business and can do it based on the path. That is, access the value of the map by its key. But I am perfectly willing to have a param/property pair if that’s what it takes.
Any suggestions? Is this a bug?
By the way, my use case is a multilingual site in which each “place” has several different content items (one per language) but they all share the same core data (address, url, etc).
Here’s another example that works nicely for creating entirely data-driven hugo sites.
Inside the data/person/demo.toml file we have a basic example person:
first = "Demo"
last = "Person"
pubname = "Demo"
github = "youraccount"
Then in layouts/student/block.html view template, (which I use to include in the _default/single.html template):
{{ with (index .Site.Data.person (substr $.File.LogicalName 0 -3)) }}
<div class="student">
<div class="student__pubname">{{ .pubname }}</div>
</div>
{{ end }}
Notice that the date is a logical person and the template is for a student type. This is because in the larger application I only have person logical data types and cast them to roles and views using this method of type views and content, which brings us to the content/student/demo.md file. It’s empty. Just add it. This is because as far as I know, Hugo doesn’t actually create any single page unless there is a corresponding content file of some kind. At first this seems annoying, but turns out it is not that bad and allows you to turn on or off a page simple by removing or touching the content file.
Thanks for this solution @robmuh. I don’t quite grasp data files fully and this is as close as got to getting mine to work how I’d like them too. Using this method how would one then range through data file?
In my single.html template I eventually got it to iterate over comments corresponding to the current post with the following (relying on a slug attribute being defined in each post):
{{ with (index .Site.Data.blog.comments .Params.slug ) }}
{{ range . }}
...
{{ end }}
{{ end }}
And to base it on the filename of the blog post rather than .Params.slug I did this to chop off the date portion of the parent directory’s name (the first 11 characters):
{{ $slug := substr (index (split .File.Dir "/") 1) 11 }}
{{ with (index .Site.Data.blog.comments $slug) }}
{{ range . }}
...
{{ end }}
{{ end }}
With either of the above, that inner {{ range . }} lets me access comment data like {{ .name }} and {{ .comment }}.