how to calculate remainder of an integer division in jinja2 - jinja2

I'm trying to make a mod in jinja2 but no way.
{% set index = 1 %}
option 1:
{% for .... %}
{% if {{index % 3 == 0}} %}
{% endif %}
{% set index = index + 1 %}
{% endfor %}
option 2:
{% for .... %}
{% if index.index is divisibleby 3 %}
{% endif %}
{% set index = index + 1 %}
{% endfor %}
Any idea?
Thanks

You just need to remove the {{ }} from your first if statement. This code works...
<!-- {% set index = 9 %} -->
{% set index = 10 %}
{% if index % 3 == 0 %}hi
{% endif %}
{% set index = index + 1 %}
Hope this helps!

You can use the batch filter:
{% for item_batched in items|batch(3) %}
{% for item in items_batched %}
{% endfor %}
{% endfor %}
http://jinja.pocoo.org/docs/dev/templates/#batch

Related

Liquid: ifelse not working and printing var in the body

I'm trying to create a home page for a simple blog with HTML and CSS. For the blog posts, I've created 2 types of cards: blog-card and blog-card alt, one to the left and one to the right, and they are meanted to be alterneted. So I did the following code:
{% assign iter = 0 %}
{% for post in site.posts %}
{% increment iter %}
{% assign itermodulo = iter | modulo: 2 %}
{% if itermodulo == 0 %}
<div class="blog-card">
...
</div>
{% else %}
<div class="blog-card alt">
...
</div>
{% endif %}
{% endfor %}
But instead of alternating the card format, all the cards are on the left (following blog-card) and the var iter is being printed on the screen. What I have to do? Thanks in advace!
Something like this should work:
{% for post in site.posts %}
{% assign itermodulo = forloop.index | modulo: 2 %}
{% if itermodulo == 0 %}
<div class="blog-card"></div>
{% else %}
<div class="blog-card alt"></div>
{% endif %}
{% endfor %}

How do I get related posts in Jekyll to work?

I wanted to modify the answer found here but it doesn't seem to be working for me as it just results in duplicate statements of "there are no related posts".
Originally, when there are no related posts, nothing is displayed and I wanted to change that. Again, at the moment, with the else statement I added, it just displays "there are no related posts" 3 times and I cant seem to figure out why.
Any help would be appreciated.
{% assign maxRelated = 0 %}
{% assign minCommonTags = 3 %}
{% assign maxRelatedCounter = 0 %}
{% for post in site.posts %}
{% assign sameTagCount = 0 %}
{% assign commonTags = '' %}
{% for tag in post.tags limit:1 %}
{% if post.url != page.url %}
{% if page.tags contains tag %}
{% assign sameTagCount = sameTagCount | plus: 1 %}
{{ post.title }}
<p>{{ post.excerpt | strip_html | truncatewords:80 }}</p>
{% assign commonTags = commonTags | append: tagmarkup %}
{% else %}
There are no related posts.
{% endif %}
{% endif %}
{% endfor %}
{% if sameTagCount >= minCommonTags %}
{% assign maxRelatedCounter = maxRelatedCounter | plus: 1 %}
{% if maxRelatedCounter >= maxRelated %}
{% break %}
{% endif %}
{% endif %}
{% endfor %}
In the linked answer there is no else block and no out put, it just generates commonTags.
{% for tag in post.tags %}
{% comment %}---> Only compare if post is
not same as current page {% endcomment %}
{% if post.url != page.url %}
{% if page.tags contains tag %}
{% assign sameTagCount = sameTagCount | plus: 1 %}
{% capture tagmarkup %} <span class="label label-default">{{ tag }}</span> {% endcapture %}
{% assign commonTags = commonTags | append: tagmarkup %}
{% endif %}
{% endif %}
{% endfor %}
Then it outputs a link as h5 in case sameTagCount is greater or equal minCommonTags.
{% if sameTagCount >= minCommonTags %}
<div>
<h5>{{ post.title }}{{ commonTags }}</h5>
</div>
...
In your case ìt outputs 'There are no related posts.' if the condition {% if page.tags contains tag %} is not true, which apparently happens three times.

Unable to use concat on `nil`

I am trying to build a related post include file for my Jekyll site. The site is based around the concept of members, attractions and parks (each as collections). Each post has a many to many relationships. I am trying to up a combined array of each of the page attributes (members, attractions and parks) loop through the array and find posts with a common number of tags.
It's quite simple but I am getting stuck with one section, not all the posts have members, attractions and parks fields so they are returning nil but the concat filter requires an array. I am trying to default the variable to an [] but it always gets set to nil. Any ideas?
Here's the code:
<ul class="row">
{% assign pageTags = [] %}{% if page.tags.first %}{% assign pageTags = page.tags %}{% endif %}
{% assign pageAttractions = [] %}{% if page.attractions.first %}{% assign pageAttractions = page.attractions %}{% endif %}
{% assign pageMembers = [] %}{% if page.members.first %}{% assign pageMembers = page.members %}{% endif %}
{% assign pageParks = [] %}{% if page.parks.first %}{% assign pageParks = page.parks %}{% endif %}
{% assign pageTagList = pageTags | concat: pageAttractions | concat: pageMembers | concat: pageParks %}
{% for post in site.documents %}
{% assign sameTagCount = 0 %}
{% assign commonTags = '' %}
{% assign postTags = [] %}{% if post.tags %}{% assign postTags = post.tags %}{% endif %}
{% assign postAttractions = [] %}{% if post.attractions %}{% assign postAttractions = post.attractions %}{% endif %}
{% assign postMembers = [] %}{% if post.members %}{% assign postMembers = post.members %}{% endif %}
{% assign postParks = [] %}{% if post.parks %}{% assign postParks = post.parks %}{% endif %}
{% assign postTageList = postTags | concat: postAttractions | concat: postMembers | concat postParks %}
{% if post.hidden == true %}
{% break %}
{% endif %}
{% for tag in postTageList %}
{% if post.url != page.url %}
{% if pageTagList contains tag %}
{% assign sameTagCount = sameTagCount | plus: 1 %}
{% capture tagmarkup %} <span class="label label-default">{{ tag }}</span> {% endcapture %}
{% assign commonTags = commonTags | append: tagmarkup %}
{% endif %}
{% endif %}
{% endfor %}
{% if sameTagCount >= minCommonTags %}
<li class="col-lg-4 col-md-12">
<div class="main-image">
</div>
<h5>{{ post.categories | first }}</h5>
<h3>{{ post.title | replace: 'Review', '' }}</h3>
<p>
{% if post.description %}
{{ post.description }}
{% else %}
{{ post.content | markdownify | strip_html | truncatewords: 20 }}
{% endif %}
</p>
<p>
Read Article →
</p>
</li>
{% assign maxRelatedCounter = maxRelatedCounter | plus: 1 %}
{% if maxRelatedCounter >= maxRelated %}
{% break %}
{% endif %}
{% endif %}
{% endfor %}
</ul>
You can see the repo here: https://github.com/dtsn/jungleskipper/blob/feature/members/_includes/related-posts.html
From the Liquid documentation:
You cannot initialize arrays using only Liquid.
You can, however, use the split filter to break a string into an array of substrings.
You should look at compact which removes any nil values from an array.
Here is a link to the doc on shopify.
Example from Liquid documentation
Input:
{% assign site_categories = site.pages | map: "category" %}
{% for category in site_categories %}
- {{ category }}
{% endfor %}
Output:
- business
- celebrities
-
- lifestyle
- sports
-
- technology
With Compact
Input:
{% assign site_categories = site.pages | map: "category" | compact %}
{% for category in site_categories %}
- {{ category }}
{% endfor %}
Output:
- business
- celebrities
- lifestyle
- sports
- technology

Nested loops in jinja2 template

I am templating JSON with jinja2 and trying to iterate through list of lists, using 4 nested loops, and it is failing with message:
"AnsibleError: template error while templating string: expected token ':', got '}'"
As original JSON template is a bit bigger, I miss to paste here simple JSON key:value pairs.
Can you please support me on this. Thanx
This is path of template where main logic is:
{ ....
"panels": [
{% set frame_meter_servers= ["frame-meter10-246-44-20", "frame-meter10-246-45-92", "frame-meter10-246-46-234"] %}
{% set frame_procstat_meter_services= ["frame-meter-clock.service", "frame-meter-web.service"] %}
{% set frame_cpanel_backend_config_cluster_nodes= ["10.246.45.189", "10.246.46.102", "10.246.44.163"] %}
{% set frame_procstat_cpanel_services= ["frame-cpanel-backend"] %}
{% set frame_services_monitoring_hosts= ["frame_cpanel_backend_config_cluster_nodes", "frame_meter_servers"] %}
{% set frame_platform_services= ["frame_procstat_cpanel_services", "frame_procstat_meter_services"] %}
{% set id = namespace(total=1) %}
{% set z = namespace(total=0) %}
{% for node in frame_services_monitoring_hosts %}
{% set nodeloop = loop %}
{% for service in frame_platform_services %}
{% if nodeloop.index == loop.index %}
{
...
"x": 0,
"y": {{ z.total }}
},
"id": {{ id.total }},
"panels": [],
...
},
{% set x = namespace(total=0) %}
{% set y = namespace(total=1) %}
{% for hosts in node %}
{% set x = namespace(total=0) %}
{% for services in service %}
{
...
"x": {{ x.total }},
"y": {{ y.total }}
},
"id": {{ id.total }},
...
},
{% set x.total = 4 + x.total %}
{% set id.total = 1 + id.total %}
{% endfor %}
{% set y.total = 6 + y.total %}
{% endfor %}
{% set y = namespace(total=4) %}
{% for hosts in node %}
{% set x = namespace(total=0) %}
{% for services in service %}
{
...
],
"valueName": "current"
} {% set x.total = 4 + x.total %} {% set id.total = 1 + id.total %} {% if not loop.last %},{% endif %}
{% endfor %}
{% set y.total = 6 + y.total %} {% if not loop.last %},{% endif %}
{% endfor %}
{% if node|length == 2 %} {% set z.total = 14 + z.total %} {% else %} {% set z.total = 20 + z.total %}{% endif %}{% if not loop.last %},{% endif %}{% set id.total = 1 + id.total %}
{% endif %}
{% endfor %}
{% set id.total = 1 + id.total %}{% if not loop.last %},{% endif %}
{% endfor %}
],
...
{% if {{ nodeloop.index }} == {{ loop.index }} %}
That is incorrect syntax; everything inside the {% and %} is conceptually Python; what you want to say is:
{% if nodeloop.index == loop.index %}
I didn't check the rest of that wall of text, but I'm super positive that if was wrong, so let's start there

Jekyll - Liquid Templating - Exclude a Category from Widget

I am attempting to rebuild a sidebar widget which shows my categories used in Jekyll. It works fine as it is now. I want to change the liquid templating to exclude one specific category link from being shown in this widget.
{% assign cat_list = site.categories %}
{% if cat_list.first[0] == null %}
{% for category in cat_list %}
<li>{{ category }} <span class="cat-count">{{ cat_list[category].size }}</span></li>
{% endfor %}
{% else %}
{% for category in cat_list %}
<li>{{ category[0] }} <span class="cat-count">{{ category[1].size }}</span></li>
{% endfor %}
{% endif %}
{% assign cat_list = nil %}
I think what I want is something like
{% for category in cat_list **UNLESS category = 'CATEGORY'** %}
But that did not work. I'm kinda stuck, is this possible?
Thank You.
Not displayed categories array :
{% assign noDisplay = "one,two,three" | split: "," %} => ["one", "two", "three"]
The test :
{% unless noDisplay contains category[0] %}
{{ category[0] }}...
{% endunless %}
Thank you, #David Jacquel
{% assign noDisplay = "CATEGORY" | split: "," %}
{% assign cat_list = site.categories %}
{% if cat_list.first[0] == null %}
{% for category in cat_list %}
<li>{{ category }} <span class="cat-count">{{ cat_list[category].size }}</span></li>
{% endfor %}
{% else %}
{% for category in cat_list %}
{% unless noDisplay contains category[0] %}
<li>{{ category[0] }} <span class="cat-count">{{ category[1].size }}</span></li>
{% endunless %}
{% endfor %}
{% endif %}
{% assign cat_list = nil %}