Listing related records in Bolt CMS - bolt-cms

I have content types Topics and Pamphlets. Pamphlets are related to topics (e.g. a pamphlet called 'Mass in B minor' could be related to the topic 'music') using 'relations' field-type:
pamphlet:
...
relations:
topics:
multiple: false
...
What I want is to list all the Music pamphlets. More exactly, I want to be able to display each topic, with a list of pamphlets related to that topic.
There's a function record.related() but it works the other way, that is, I can use it when I display a pamphlet to show that the pamphlet is related to Music; but I can't use it when I display the Music topic to list all the pamphlets that are related to music.
(The documentation says that relations are always bi-directional, but I can't see how.)
Suggestions welcomed.

I was simply wrong when I said that the related records() function didn't do the job. Here we are (nicked from the out-of-the-box record.twig template):
{% set relatedrecords = record.related() %}
{% if relatedrecords is not empty %}
<p> Examples:</p>
<ul>
{% for related in relatedrecords %}
<li><a href="{{ related.link }}">
{{ related.title }}</a></li>
{% endfor %}
</ul>
{% endif %}
In general, it seems, if A (a pamphlet) is related to B (a topic), exactly the same method can be used to show either the topic to which a given pamphlet belongs, or the pamphlets belonging to a given topic.
Apologies for getting this wrong, and congrats to the Bolt developers for a neat bit of work.

I now have an inefficient solution. Maybe someone can improve it.
To display all the pamphlets related to a given topic, I created a template topic.twig. Within that template, record.title contains the name of the topic (eg 'Music') and record.id contains the ID of the topic. We need to select pamphlets that are marked as related to a topic with that ID. The following code fetches all the pamphlets into pamphletlist then considers each one. Using the valuable dump() function, I found that the data structure for a pamphlet includes an array relation which includes an array topics. The code below works because in my data, one pamphlet can only be related to one topic. Code:
{# to get a list of all pamphlets related to this topic #}
{% setcontent pamphletlist = 'pamphlets' %}
{% for p in pamphletlist %}
{{ dump(p) }}
{% for t in p.relation.topics %}
{% if record.id == t %}
<p> {{ p.title }} </p>
{% endif %}
{% endfor %}
{% endfor %}
It would surely be more efficient to use a where clause, something like this:
{% setcontent pamphletlist = 'pamphlets' where { relation.topics: ... } %}
That would presumably get the election done at the database level, instead of peeking at each record in turn. But my experiments only produced twig syntax errors. Does anyone have a more efficient method?

Have you looked at the Related Content by Tags extension?
This gives you a list of related content by tags:
http://extensions.bolt.cm/view/45073af0-8585-4d5b-b978-fd6405858e0e

Related

How to get all blogs in Shopify store on any page?

I'm building a Shopify store and I want to create a list of recent blog posts and products, in chronological order of publication.
However I'm stumbling at the first hurdle as I am unable to access anything from the blogs. I have tried plugging both these solutions into my code and neither produces any output.
One
Two
I'm trying to show this list on the index/custom page, can the blogs global object only be accessed inside the blog template?
Any help/pointers appreciated!
Yes, you can access the global variable in Shopify on any homepage, collection, or the product page.
Here is the list of global variables into Shopify
More read about articles here.
and use like
{% assign article = articles['news'] %}
{{ article.title | link_to: article.url }}
or use blogs global object to get the articles using the handle.
{% for article in blogs.blog-handle.articles %}
{{- article.title | link_to: article.url }}
{% endfor %}
here blog-handle is your handle slug want to fetch articles.

Counting items in Django templates

Is it possible to tally items being listed as part of the django template within the html?
For example, I have a django template with the following code snippet in it:
<div>
{% for thing in thing_list %}
{% if thing.status == "n" %}
<a>{{ thing.status.count }}</a>
{% endif %}
{% endfor %}
</div>
This django template displays all of the things in a list, and I can call each attribute of the thing and display it, so I know I have access to all of the fields.
I want to count then number of "things" and display that number as text. My current attempt above isn't working. Does anyone have any suggestions?
As Willem says, you should do this in the view. Rather than passing a list of all Things and then checking their status in the template with if, you should filter your Things when querying them from the database in the first place:
thing_list = Thing.objects.filter(status='n')
Then you can do just {{ thing_list.count }} in the template.

Random access contents of Jekyll collection

I'm using a Jekyll collection to generate a reveal.js presentation. Each file in the collection represents one slide and are named sequentially, eg 01.md, 02.md, etc. This all works fine but I want to find a more flexible method to order slides.
If I can randomly access the files in the collection, rather than sequentially iterate through them, I could maintain the order of slides external to the collection - something like: [0,1,3,2,4].
Where the collection is defined as:
collections:
reality:
title: Reality Slide Deck
output: false
I can get the content of item 3 of the collection with:
{{site.reality[3].content}}
How do I access the front matter?
Thanks in advance.
Any front matter's variable is available under is own name.
{{site.reality[3].title}}
or
{{site.reality[3].variableName}}
You can loop through the content of your site using site.collection as is explained in the documentation at https://jekyllrb.com/docs/collections/#documents
To access only one collection you can use a conditional statement.
{% for info in site.collections %}
<ul>
<li>{{ info }}</li>
<li>The name of the collection: {{ info.label }}</li>
{% for stuff in info.docs %}
<li>{{ stuff.title }}</li>
{% endfor %}
</ul>
{% endfor %}
After saying all of this you can of course just loop through the one collection as below:
{% for real in site.reality %}
<li>{{ real.title }}</li>
{% endfor %}
The only other method that may work it to create an array using liquid syntax
{{ "a~b" | split:"~" }} #=> ['a','b']
Not sure if this answers your question, I hope it's useful for someone.

Jekyll: Is there anyway to output all posts and collection types in a single for loop ordered by date?

I have two collections defined for tutorials and articles within my Jekyll blog. I need to be able to display all the different collection types alongside posts and have them ordered by date. Is there anyway to do this?
Thank you.
That can be done with some liquid code. By looping first over all collections one can capture the collection labels and use these to access all documents in all collections in a second for-loop.
{% for collection in site.collections %}
{% capture label %}{{ collection | first }}{% endcapture %}
<h3>All documents listed in collection '{{ label}}'</h3>
{% for doc in site.collections.[label].docs %}
<li>
<span>{{ doc.date | date_to_string }}</span>
{{ doc.title }}
</li>
{% endfor %}
{% endfor %}
This lists dates and titles of all documents per collection in chronological order. However, if one want all documents sorted in one list things get nasty. I hope, something similar to the code above is what you are looking for.

Generating a list of pages (not posts) in a given category

I am using Jekyll as a static generator for a website (not a blog), and I want to have an automatically generated list of all pages on my index page. Specifically, I want to have different categories and list all articles in each category separately. Here's an example of what I'm describing, if you're having trouble following. Is there any way to do this in Jekyll (e.g. GitHub pages)? I've seen the variables documentation page but that seems specific to the blog post format.
While building my own site I came across this very same problem, and I have found an (IMHO) easy and robust solution.
The Problem
Given a subset of pages (not posts) on the site, list them under headings based on their categories. For example: given a set of pages which we consider resource pages (or reference pages, or whatever logical grouping of pages that you want to display are), we want to list them under their categories (ex. code, explanation, et cetera).
The Solution
To get the behaviour that we want, we have to make modifications in three places:
_config.yml
resources.md
resource-file-X.md
_config.yml
In _config.yml, we must add a list of all of the categories/keywords/tags (or whatever you want to call it) that will appear in the resource files. Here is what I have in mine:
category-list: [code, editors, math, unix]
You can call the variable anything, I chose category-list, just make sure that you use the same variable in the resource.md file.
Note: The order that you place the items in the list is the order they will be listed on the resource.md page.
resource-file-X.md
These are the files that you want to have indexed and linked to on the resources.md page. All that you need to do is add two file variables to the top of each of these files. The first is to indicate that this file is a resource file.
resource: true
The second is to indicate what categories you want this file to be indexed under. You can index it under as many categories as you would like, and if you want a page un-indexed, leave the list blank. My reference for proper EINTR handling in C has the following categories:
categories: [code, unix]
resources.md
This is the file that will generate the list of pages based on their respective categories. All you need to do is add the following code to this file (or whatever file you want the list to be on):
{% for cat in site.category-list %}
### {{ cat }}
<ul>
{% for page in site.pages %}
{% if page.resource == true %}
{% for pc in page.categories %}
{% if pc == cat %}
<li>{{ page.title }}</li>
{% endif %} <!-- cat-match-p -->
{% endfor %} <!-- page-category -->
{% endif %} <!-- resource-p -->
{% endfor %} <!-- page -->
</ul>
{% endfor %} <!-- cat -->
Code Breakdown
Just a quick explanation of how this works:
Loop through each of the categories specified in _config.yml.
Display a heading with that category name.
Start an unordered list for the pages that belong in that category.
Loop through the pages on the site.
If the page is a resource file as indicated by the file variable resource, then for each of the categories that the file belongs to, if one of them matches the current category being listed, display a link to that page.
Note: the variables category-list in _config.yml and categories in the resource files can be called whatever you want, just make sure that you use the same variables in the file generating the list.
Another Note: When you modify _config.yml, you have to completely restart Jekyll, even if you have the --watch option, you have to stop and restart it. It took me a while to figure out why my changes weren't taking effect!
The Final Product
You can see the final product on the resources page on my site, although I just put this together today so at the time of this writing, it's far from complete, but you can check out my bio if you want on the home page.
There's a cleaner way to do this using the liquid "contains" property:
In _config.yml, add your index of categories
categories: [fruit, meat, vegetable, cheese, drink]
In your page.md inside the front matter, add one or more of the categories available in the _config.yml
---
layout: page
title: Orange juice
description: Orange juice is juice from oranges. It's made by squeezing oranges.
categories: [fruit, drink]
---
In your template to get all the pages in the fruit category you do:
{% for page in site.pages %}
{% if page.categories contains 'fruit' %}
<div class="item">
<h3>{{page.title}}</h3>
<p>{{page.description}}</p>
</div>
{% endif %}
{% endfor %}
You should differentiate between pages and posts (articles). Listing all posts sorted by category is not a problem at all. You can loop through site.categories. It contains the category name and a list of all posts in that category.
Listing all pages is possible, too. You can loop through site.pages. But a page does not belong to a specific category (only posts do).
When I take a look at your posted example, using categories on posts and then looping through site.categories seems to be the way to go. It will get you exactly the desired output.
There are some variations/ simplifications possible (answer of felipesk). Maybe due to improvements in Jekyll.
There is NO index needed in _config.yml.
If the list of pages are not listed in a page but for example in a doc, you can add the category also to the doc:
---
layout: doc
title: Fruit List
categories: [fruit]
---
And then use it like this:
{% for p in site.pages %}
{% if p.categories contains page.category %}
* [{{ p.title }}]({{ p.url | absolute_url }})
<small>{{ p.excerpt }}</small>
{% endif %}
{% endfor %}
With posts this can even be shorter:
{% for post in site.categories[page.category] %}
* [{{ post.title }}]({{ post.url | absolute_url }})
<small>{{ post.excerpt }}</small>
{% endfor %}
Why this only works for posts, I could not figure out yet.
The interesting point is that this snippet can be used everywhere (if you mix docs/pages/posts)!
So just add it as an _includes and use it like:
## Further Reading
{% include pages-list.md %}
I work with the theme Minimal Mistakes