简体   繁体   English

Jinja2 Output Markdown

[英]Jinja2 Output Markdown Frontmatter to List

I have a folder of Markdown files.我有一个 Markdown 文件的文件夹。 Each file contains a block of YAML frontmatter.每个文件都包含一个 YAML frontmatter 块。 I am trying to output the title's from each file's frontmatter into a Jinja2 template, and list them all in a HTML file.我正在尝试将 output 标题从每个文件的 frontmatter 转换为 Jinja2 模板,并将它们全部列出在 HTML 文件中。

I have no issue displaying the titles without Jinja2, but it all falls apart when I try to output to my Jinja2 template.在没有 Jinja2 的情况下显示标题没有问题,但是当我尝试将 output 转换为我的 Jinja2 模板时,一切都崩溃了。

Here's an example of the Markdown files I'm working with, and the title: item I am trying to list:这是我正在使用的 Markdown 文件的示例, title:我要列出的项目:

---
title: Test
date: 2020-03-26
---

## Test Markdown

Here's the Python code I am using.这是我正在使用的 Python 代码。 I'm using the python-frontmatter module to extract the frontmatter from each Markdown post.我正在使用python-frontmatter模块从每个 Markdown 帖子中提取frontmatter。

Using the frontmatter module it's really easy to select the title and display it on the terminal, but I'm not getting anywhere with the Jinja2 template.使用 frontmatter 模块很容易 select 标题并将其显示在终端上,但使用 Jinja2 模板我没有得到任何结果。 content.metadata is a dict. content.metadata是一个字典。

import frontmatter
import jinja2
import glob

# Initialise Jinja2:
jinja2_env = jinja2.Environment(
    loader=jinja2.FileSystemLoader("templates"),
)

# Get list of posts:
posts = glob.glob("posts/*.md")

def build():

    with open("test.html", "w", encoding="utf-8") as index_file:
        for post in posts:
            content = frontmatter.load(post)

            # Prints titles to the terminal the way I want to output them in the Jinja template:
            print(content.metadata["title"])

            # Jinja output:
            template = jinja2_env.get_template("test.html.j2")
            rendered = template.render(frontmatter=content.metadata)
            index_file.write(rendered)

build()

My Jinja2 template looks like this:我的 Jinja2 模板如下所示:

<ul>
{% for key, value in frontmatter.items() %}
    <li><a href="">{{ value.title() }}</a></li>
{% endfor %}
</ul>

This doesn't work at all, and I get an error jinja2.exceptions.UndefinedError: 'datetime.datetime object' has no attribute 'title' .这根本不起作用,我收到错误jinja2.exceptions.UndefinedError: 'datetime.datetime object' has no attribute 'title' If I remove .title() then the HTML file that gets created ends up looping through the dicts but outputs the full template for each one:如果我删除.title() ,则创建的 HTML 文件最终会遍历字典,但会为每个字典输出完整的模板:

<ul>

    <li><a href="">Test Title 1</a></li>

    <li><a href="">2020-10-21 10:00:20</a></li>

</ul><ul>

    <li><a href="">Test Title 2</a></li>

    <li><a href="">2019-06-09 17:42:12</a></li>

</ul><ul>

    <li><a href="">Test Title 3</a></li>

    <li><a href="">2019-06-09 17:42:12</a></li>

</ul>

I'm at the limits of my Python knowledge here, so any help on resolving this would be great.我在这里的 Python 知识有限,所以解决这个问题的任何帮助都会很棒。 What I want at the end of it all is an HTML file that outputs each file's title like this:最后我想要的是一个 HTML 文件,它输出每个文件的标题,如下所示:

<ul>
    <li><a href="">Test Title 1</a></li>
    <li><a href="">Test Title 2</a></li>
    <li><a href="">Test Title 3</a></li>
</ul>
<ul>
{% for key, value in frontmatter.items() %}
    <li><a href="">{{ value.title() }}</a></li>
{% endfor %}
</ul>

This is wrong.这是错误的。 Like the error message says, you're calling title() on a datetime object (your date front matter).就像错误消息说的那样,您在日期时间 object (您的date前事项)上调用title() ) 。

Your loop is iterating over every key (title, then date) in the front matter, as well as the value .您的循环正在遍历前面的每个key (标题,然后是日期)以及value

<ul>
    <li><a href="">{{ frontmatter.title }}</a></li>
    <li>{{ frontmatter.date }}</li>
</ul>

Of course, this is only going to show you the title for one of your source files, because you are looping over every post and rendering them as entirely separate templates:当然,这只会显示您的一个源文件的标题,因为您正在遍历每个帖子并将它们呈现为完全独立的模板:

for post in posts:

You want to render 1 template, so remove the for loop around your call to render() and pass it all of your posts:您要渲染1 个模板,因此请删除您对render()调用的 for 循环并将其传递给您的所有帖子:

rendered = template.render(
    posts=posts,
    posts_meta=[frontmatter.load(post).metadata for post in posts]
)

... and loop over them in your template: ...并在您的模板中循环它们:

<ul>
{% post_meta in posts_meta %}
    <li><a href="">{{ post_meta.title }}</a></li>
{% endfor %}
</ul>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM