【问题标题】:How do you include flask/jinja2 code inside a markdown file?如何在 markdown 文件中包含 flask/jinja2 代码?
【发布时间】:2015-08-26 17:29:30
【问题描述】:

我正在使用由

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

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

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

而不是实际值。

【问题讨论】:

  • 请发帖MCVE。这里没有足够的代码来诊断这个问题。
  • 在某些时候你必须调用jinja2 来渲染你的模板。你在这样做吗?
  • 您必须将呈现的文本包装在 Template() 对象中,然后才能将其实际视为模板。您不能只将带有 Jinja2 标记的文本插入到模板中,并期望该文本被视为模板本身。

标签: python flask markdown jinja2


【解决方案1】:

我最近在不同的地方看到了这个问题,无论是与 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 解析器转换为 HTML 的 Markdown 文本。如果您希望颠倒处理顺序,则需要切换代码以首先运行 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 文本并返回 HTML 文本,然后将其放入模板中。在这种情况下,不会发生模板语法处理。事实上,这样做可能会导致安全问题,尤其是当 Markdown 文本是由不受信任的用户提供时。因此,任何包含模板语法的 Markdown 文本都必须单独处理模板语法。

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

【讨论】:

  • 哇,有人能抓住我!你击中了头上的每一个钉子。这正是我所缺少的概念。谢谢你填补了空白,你才是真正的mvp。
猜你喜欢
  • 2013-01-24
  • 1970-01-01
  • 2016-10-12
  • 2014-05-16
  • 1970-01-01
  • 1970-01-01
  • 2018-10-09
  • 2019-01-01
  • 2017-09-20
相关资源
最近更新 更多