Filter pages based on specific author

Hey all!

I’m trying to figure out the where clause that will let me filter based on an item’s sub-list. This is my latest attempt, but it’s failing:

{{ $author_pubs:= where (where .Site.Pages "Section" "publication") $member_id "in" "Params.Authors" }}

The inner where clause is doing the right thing, and $member_id is set right. For clarity, this code…

<pre>{{ $member_id }}</pre>
<pre>{{ where .Site.Pages "Section" "publication" }}</pre>
<pre>{{ (index (where .Site.Pages "Section" "publication") 0).Params.Authors }}</pre>

…gets rendered as:

Unfortunately, my $author_pubs is empty.

Aside from a fix to the set building above, I’d be curious as to how to debug this all better – currently I’m just guessing at parameters and re-deploying the site to check. Any tips would be greatly appreciated!

Hi there,

It is easier to help you if we can replicate your issue. Please have a read about Requesting Help .

Sure thing. I’m sure this is a simple silly thing, which is why I was hoping the syntax above was enough to show what I’ve been doing wrong. Here’s a MWE I just through together:

My ID appears on 2 of the 3 paper files: content/papers

This is the fairly empty test page (just fires up the layout): content/page/

And this shows what fails: hugo-issue/test.html at main · haz/hugo-issue · GitHub

(only included the two most important links, since I’m limited to 2 URLs in a post as a new user)

I understand what’s going on with all the lines but the last. I’ve also tried a wide variety of things for the last, to no avail. Just want the list of “paper” pages that have a particular author listed. Don’t want to iterate through them all and output things as need be, because this will ultimately be wrapped in a first functionality to grab the most recent 5 papers.

Do let me know if there’s anything else I can provide!

From where | Hugo :


true if a given field value is included in a matching value; a matching value must be an array or a slice

The value of the field “.Params.Authors” is a list of maps, which you are trying to match against a string.

{{ $authorpapers := slice }}
{{ range $papers }}
{{ $p := . }}<!-- store current page iteration -->
    {{ with .Params.authors }}
        {{ if gt (len (where . "id" $member_id)) 0 }}
   <!-- where statement returns slice containing  matches to[i].id == $member_id -->
   <!-- gt 0 means the paper includes this author, so store the page. -->
            {{ $authorpapers = $authorpapers | append $p }}
        {{ end }}
    {{ end }}
{{ end }}

{{ $authorpapers }}
{{ first 5 ( sort $authorpapers "Date" "desc" ) }}

Wild. I’m unfamiliar with slice, but that method of having a large block to build the right list is something I’d assumed would work, but is sub-optimal.

Ya, that makes sense. If I rewrite the targetted line, and abuse the notation to a point that obviously doesn’t parse, this is what I was after:

{{ $author_pubs:= where (where .Site.Pages "Section" "publication") $member_id "in" <current publication item's author list ID's> }}

If it was Python, then something like [ for author in pub.authors]. I thought apply might come to the rescue, but I couldn’t make that fly either.

So no advanced one-liner that would capture the same as the $authorpapers block you gave? Either way, thanks for all the advice!

If you have control over your content, you could use Taxonomies instead.

<!-- papers/ -->
authors = ["john.doe", ""]
## config.toml
author = "authors"
<!-- content/page/ -->
id: "john.doe"
<!-- content/authors/john.doe/ -->
name = "John Doe"
is_member = true
{{ $member_id }}
{{ $author := (site.GetPage (print "authors/" $member_id)) }}
{{ $ }} / {{ $author.Params.is_member }}
{{ $author.Pages }}
{{ where $author.Pages "Section" "papers" }}

John Doe / true

Code like that in theme widget works as expected - filtering pages by his author

{{ if $ }}
  {{ $archive_page = site.GetPage (printf "authors/%s" (urlize $ }}
  {{ $query = $query | intersect $archive_page.Pages }}
{{ end }}

UPD. some explanation - to get pages with any filter the simplest way is using intersect function which are have too sets as a parameters and return items which are present in both sequences. So if you can get all posts or any pages in sections or needed type/kind, after that you should retrieve ones more sequence of pages with needed params and intersect its to get common elements of both.

Hope this helps you :grinning:

Thank you both! I think I’ll run with the first option since it’s the simplest for me to grok and extend as more requirements come to the fore. Really appreciate the dive into this!

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.