如何在降价文件中包含 flask/jinja2 代码?

How do you include flask/jinja2 code inside a markdown file?

我正在使用由

转换的降价编辑器
post_body = markdown(text_from_markdown_editor)

但是当我渲染 html 时,会显示实际的 jinja2 代码

This is a post by {{ post.author }} 

而不是实际值。

我最近看到这个问题在不同的地方出现了很多,都与 Jinja 和 Django 模板有关。对于模板系统的工作方式以及它与渲染到 HTML 并插入到模板中的 Markdown 文本的关系,似乎存在根本性的误解(在某些用户中)。我会尽力解释清楚。请注意,虽然下面的答案适用于大多数模板系统(包括 Jinja 和 Django),但示例使用 Jinja 用于说明目的(毕竟,原始问题专门询问了 Jinja)。只需调整代码以匹配您选择的模板系统的 API,它应该也能正常工作。

首先,Markdown 对模板语法一无所知。事实上,Markdown 比 Jinja、Django 或其他各种流行的模板系统存在的时间更长。此外,Markdown Syntax Rules 没有提及模板语法。因此,您的模板语法不会简单地通过 Markdown 解析器传递一些包含模板语法的 Markdown 文本来处理。模板语法需要模板引擎单独处理。例如:

from jinja2 import Environment
# Set up a new template environment
env = Environment()
# Create template with the markdown source text
template = env.from_string(text_from_markdown_editor)
# Render that template. Be sure to pass in the context (post in this instance).
template_processed_markdown = template.render(post=post)
# Now pass the Markdown text through the Markdown engine:
post_body = markdown(template_processed_markdown)

注意上面先处理模板语法,再解析Markdown。换句话说,模板处理的输出仍然是标记被适当值替换的 Markdown 文本。仅在最后一行,Markdown 解析器将 Markdown 文本转换为 HTML。如果你想颠倒处理顺序,你需要先将代码切换到 运行 Markdown 解析器,然后将其输出传递给模板处理器。

我假设一些混淆来自人们通过模板系统传递 Markdown 文本。这不应该导致模板语法被处理吗?总之,没有。

模板系统的核心是采用模板和上下文。然后,它会在模板中找到各种标签,并将这些标签替换为上下文中提供的匹配数据。但是,模板不知道上下文中的数据,也不处理该数据。例如,此模板:

Hello, {{ name }}!

而这个上下文:

output = template(name='John')

将导致以下输出:

Hello, John!

但是,如果上下文是这样的:

output = template(name='{(some_template_syntax)}')

那么输出将是:

Hello, {{some_template_syntax}}!

请注意,虽然上下文中的数据包含模板语法,但模板并未处理该数据。它只是将其视为一个值并将其按原样插入到模板中的适当位置。这是正常且正确的行为。

但是,有时您可能有合理的需求,需要模板对传递给模板的某些数据进行一些额外的处理。因此,模板系统提供了过滤器。当在上下文中给定一个变量时,过滤器将处理该变量中包含的数据,然后将处理过的数据插入到模板中。例如,要确保我们前面示例中的名称大写,模板将如下所示:

Hello, {{ name|capatalize }}!

传入上下文output = template(name='john')(注意名字是小写的),然后我们得到如下输出”

Hello, John!

注意,name变量中的数据经过首字母大写处理,这是Jinja内置过滤器capitalize的功能。但是,该过滤器不处理模板语法,因此将模板语法传递给该过滤器不会导致处理模板语法。

相同的概念适用于任何 markdown 过滤器。这样的过滤器仅将提供的数据解析为 Markdown 文本和 returns HTML 文本,然后将其放入模板中。在这种情况下不会处理模板语法。事实上,这样做可能会导致安全问题,尤其是当不受信任的用户提供 Markdown 文本时。因此,任何包含模板语法的 Markdown 文本都必须单独处理模板语法。

但是,有一点需要注意。如果您正在编写的文档中包含模板语法示例作为代码块(例如此答案的 Markdown 源代码),则模板系统不会知道其中的区别,并且会像处理任何不在代码中的模板语法一样处理这些标签堵塞。如果首先完成 Markdown 处理,以便将生成的 HTML 传递给模板系统,那么 HTML 仍将在代码块中包含未更改的模板语法,这些代码块仍将由模板系统处理。在任何一种情况下,这很可能都不是所希望的。作为一种解决方法,可以想象创建某种 Markdown 扩展,它将语法处理添加到 Markdown 处理器本身。但是,这样做的机制会根据使用的 Markdown 处理器而有所不同,并且超出了本 question/answer.

的范围。