pimenz
pimenz

Reputation: 121

Filter blog posts by tag field

I'm trying to create a page/view which filters out blog posts by post tags like this website made using Lektor, on this website only posts with a linux tag get displayed on the /blog/tag/tagname page https://terminallabs.com/blog/tag/linux/.

What I have achieved so far:

I've added a field called tags of type strings to the blog-post.ini file (see below).

[fields.tags] 
label= Post tags 
type = strings 
description = Put each tag on its own line

I've managed to display every unique tag name using the below construct and then looping through tags.

{% set tags = site.query('/blog').distinct('tags') %}
{% if tags %}
<ul>
    {% for tag in tags|sort %}
    <li><a href="{{ tag }}">{{ tag }}</a></li>
    {% endfor %}
</ul>
{% endif %}

Now I have 2 issues. First one, I cannot make the href value of the link in the code snippet above become blog/tag/tagname on every page. Instead, it displays as projects/tagname or about/tagname depending on the page being visited. I need it to always display as:

<li><a href="blog/tag/tagname">{{ tag }}</a></li>

My second issue is I don't understand how to filter out the posts with that specific tag when the /blog/tag/tagname page gets visited. I suppose the render_blog_post macro should be modified to receive a tag argument and then inside that macro check that the actual post has this tag or not. If the tag is present then display the post, else not.

  {% block body %}   
        {% for child in this.pagination.items %}
            {{ render_blog_post(child, from_index=true, tag) }}   
        {% endfor %}
    
        {{ render_pagination(this.pagination) }} 
{% endblock %}

Could you please tell me if I'm on the right path, is my logic correct and how to achieve this?

Really appreciate your help and input!

Upvotes: 0

Views: 224

Answers (1)

pimenz
pimenz

Reputation: 121

I've figured out the solution, so posting it here to ease the solution of this problem for others, shall they face it.

Essentially, tags are called categories in Lektor. So I followed the guide at https://www.getlektor.com/docs/guides/categories/ as a starting point.

Then, to display the tags at the main page, I added this code snippet in layout.html, and the url led to the correct filter page. My model is called blog-categories instead of project-categories. If you are following lektor's guide replace /blog-categories with /project-categories in the site.query statement below.

<ul>
 {% for category in site.query('/blog-categories') %}
     <li><a href="{{ category|url }}">{{ category.name }}</a></li>
 {% endfor %}
</ul>

To display the actual filtered posts I added this slightly modified code to blog-category.html file, which is called project-category.html in lektor's original guide:

{% extends "layout.html" %}
{% from "macros/blog.html" import render_blog_post %}
{% block title %}Project Category {{ this.name }}{% endblock %}
{% block body %}
  <h1>Project Category {{ this.name }}</h1>
  {% for child in this.children %}
 {{ render_blog_post(child, from_index=true) }}
 {% endfor%}
{% endblock %}

This allowed me to reuse the same macro code that is used to render the preview of all the blog posts to render the preview of only the filtered (tagged) posts.

Hope this helps somebody.

Upvotes: 0

Related Questions